diff --git a/crates/aiken-lang/src/parser/annotation.rs b/crates/aiken-lang/src/parser/annotation.rs index c19aeff4..7b0f5244 100644 --- a/crates/aiken-lang/src/parser/annotation.rs +++ b/crates/aiken-lang/src/parser/annotation.rs @@ -89,3 +89,13 @@ pub fn parser() -> impl Parser { )) }) } + +#[cfg(test)] +mod tests { + use crate::assert_annotation; + + #[test] + fn type_annotation_with_module_prefix() { + assert_annotation!("aiken.Option"); + } +} diff --git a/crates/aiken-lang/src/parser/definition/function.rs b/crates/aiken-lang/src/parser/definition/function.rs index 4b61939e..235e433a 100644 --- a/crates/aiken-lang/src/parser/definition/function.rs +++ b/crates/aiken-lang/src/parser/definition/function.rs @@ -87,3 +87,26 @@ pub fn param(is_validator_param: bool) -> impl Parser impl Parser impl Parser impl Parser { arg_name, }) } + +#[cfg(test)] +mod tests { + use crate::assert_expr; + + #[test] + fn anonymous_function_basic() { + assert_expr!(r#"fn (a: Int) -> Int { a + 1 }"#); + } +} diff --git a/crates/aiken-lang/src/parser/expr/assignment.rs b/crates/aiken-lang/src/parser/expr/assignment.rs index 4b25431a..0759f223 100644 --- a/crates/aiken-lang/src/parser/expr/assignment.rs +++ b/crates/aiken-lang/src/parser/expr/assignment.rs @@ -43,3 +43,13 @@ fn assignment( }, ) } + +#[cfg(test)] +mod tests { + use crate::assert_expr; + + #[test] + fn let_bindings() { + assert_expr!(r#"let thing = [ 1, 2, a ]"#); + } +} diff --git a/crates/aiken-lang/src/parser/expr/record_update.rs b/crates/aiken-lang/src/parser/expr/record_update.rs index 11dc9ea6..4565be12 100644 --- a/crates/aiken-lang/src/parser/expr/record_update.rs +++ b/crates/aiken-lang/src/parser/expr/record_update.rs @@ -84,3 +84,13 @@ pub fn parser( } }) } + +#[cfg(test)] +mod tests { + use crate::assert_expr; + + #[test] + fn record_update_basic() { + assert_expr!(r#"User { ..user, name: "Aiken", age }"#); + } +} diff --git a/crates/aiken-lang/src/parser/expr/snapshots/anonymous_function_basic.snap b/crates/aiken-lang/src/parser/expr/snapshots/anonymous_function_basic.snap new file mode 100644 index 00000000..da64b10f --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/anonymous_function_basic.snap @@ -0,0 +1,51 @@ +--- +source: crates/aiken-lang/src/parser/expr/anonymous_function.rs +description: "Code:\n\nfn (a: Int) -> Int { a + 1 }" +--- +Fn { + location: 0..28, + fn_style: Plain, + arguments: [ + Arg { + arg_name: Named { + name: "a", + label: "a", + location: 4..5, + is_validator_param: false, + }, + location: 4..10, + annotation: Some( + Constructor { + location: 7..10, + module: None, + name: "Int", + arguments: [], + }, + ), + tipo: (), + }, + ], + body: BinOp { + location: 21..26, + name: AddInt, + left: Var { + location: 21..22, + name: "a", + }, + right: Int { + location: 25..26, + value: "1", + base: Decimal { + numeric_underscore: false, + }, + }, + }, + return_annotation: Some( + Constructor { + location: 15..18, + module: None, + name: "Int", + arguments: [], + }, + ), +} diff --git a/crates/aiken-lang/src/parser/expr/snapshots/let_bindings.snap b/crates/aiken-lang/src/parser/expr/snapshots/let_bindings.snap new file mode 100644 index 00000000..71e556c8 --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/let_bindings.snap @@ -0,0 +1,37 @@ +--- +source: crates/aiken-lang/src/parser/expr/assignment.rs +description: "Code:\n\nlet thing = [ 1, 2, a ]" +--- +Assignment { + location: 0..23, + value: List { + location: 12..23, + elements: [ + Int { + location: 14..15, + value: "1", + base: Decimal { + numeric_underscore: false, + }, + }, + Int { + location: 17..18, + value: "2", + base: Decimal { + numeric_underscore: false, + }, + }, + Var { + location: 20..21, + name: "a", + }, + ], + tail: None, + }, + pattern: Var { + location: 4..9, + name: "thing", + }, + kind: Let, + annotation: None, +} diff --git a/crates/aiken-lang/src/parser/expr/snapshots/record_update_basic.snap b/crates/aiken-lang/src/parser/expr/snapshots/record_update_basic.snap new file mode 100644 index 00000000..69e8ebb8 --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/record_update_basic.snap @@ -0,0 +1,43 @@ +--- +source: crates/aiken-lang/src/parser/expr/record_update.rs +description: "Code:\n\nUser { ..user, name: \"Aiken\", age }" +--- +RecordUpdate { + location: 0..35, + constructor: Var { + location: 0..4, + name: "User", + }, + spread: RecordUpdateSpread { + base: Var { + location: 9..13, + name: "user", + }, + location: 7..13, + }, + arguments: [ + UntypedRecordUpdateArg { + label: "name", + location: 15..28, + value: ByteArray { + location: 21..28, + bytes: [ + 65, + 105, + 107, + 101, + 110, + ], + preferred_format: Utf8String, + }, + }, + UntypedRecordUpdateArg { + label: "age", + location: 30..33, + value: Var { + location: 30..33, + name: "age", + }, + }, + ], +} diff --git a/crates/aiken-lang/src/parser/snapshots/type_annotation_with_module_prefix.snap b/crates/aiken-lang/src/parser/snapshots/type_annotation_with_module_prefix.snap new file mode 100644 index 00000000..44243da9 --- /dev/null +++ b/crates/aiken-lang/src/parser/snapshots/type_annotation_with_module_prefix.snap @@ -0,0 +1,19 @@ +--- +source: crates/aiken-lang/src/parser/annotation.rs +description: "Code:\n\naiken.Option" +--- +Constructor { + location: 0..17, + module: Some( + "aiken", + ), + name: "Option", + arguments: [ + Constructor { + location: 13..16, + module: None, + name: "Int", + arguments: [], + }, + ], +} diff --git a/crates/aiken-lang/src/parser/utils.rs b/crates/aiken-lang/src/parser/utils.rs index a4150279..2e1716ce 100644 --- a/crates/aiken-lang/src/parser/utils.rs +++ b/crates/aiken-lang/src/parser/utils.rs @@ -115,6 +115,27 @@ macro_rules! assert_expr { }; } +#[macro_export] +macro_rules! assert_annotation { + ($code:expr) => { + use chumsky::Parser; + + let $crate::parser::lexer::LexInfo { tokens, .. } = $crate::parser::lexer::run(indoc::indoc! { $code }).unwrap(); + + let stream = chumsky::Stream::from_iter($crate::ast::Span::create(tokens.len()), tokens.into_iter()); + + let result = $crate::parser::annotation().parse(stream).unwrap(); + + insta::with_settings!({ + description => concat!("Code:\n\n", indoc::indoc! { $code }), + prepend_module_to_snapshot => false, + omit_expression => true + }, { + insta::assert_debug_snapshot!(result); + }); + }; +} + #[macro_export] macro_rules! assert_module { ($code:expr) => { diff --git a/crates/aiken-lang/src/tests/parser.rs b/crates/aiken-lang/src/tests/parser.rs index 8b9e6d59..e927ac2d 100644 --- a/crates/aiken-lang/src/tests/parser.rs +++ b/crates/aiken-lang/src/tests/parser.rs @@ -1,31 +1,5 @@ use crate::assert_module; -#[test] -fn type_annotation_with_module_prefix() { - assert_module!( - r#" - use aiken - - pub fn go() -> aiken.Option { - False - } - "# - ); -} - -#[test] -fn test_fail() { - assert_module!( - r#" - !test invalid_inputs() { - expect True = False - - False - } - "# - ); -} - #[test] fn custom_type() { assert_module!( @@ -50,33 +24,6 @@ fn opaque_type() { ); } -#[test] -fn type_alias() { - assert_module!( - r#" - type Thing = Option - "# - ); -} - -#[test] -fn pub_type_alias() { - assert_module!( - r#" - pub type Me = Option - "# - ); -} - -#[test] -fn empty_function() { - assert_module!( - r#" - pub fn run() {} - "# - ); -} - #[test] fn expect() { assert_module!( @@ -113,26 +60,6 @@ fn pipeline() { ); } -#[test] -fn let_bindings() { - assert_module!( - r#" - pub fn wow(a: Int) { - let x = - a + 2 - |> add_one - |> add_one - - let thing = [ 1, 2, a ] - - let idk = thing - - y - } - "# - ); -} - #[test] fn block() { assert_module!( @@ -169,19 +96,6 @@ fn when() { ); } -#[test] -fn anonymous_function() { - assert_module!( - r#" - pub fn such() -> Int { - let add_one = fn (a: Int) -> Int { a + 1 } - - 2 |> add_one - } - "# - ); -} - #[test] fn field_access() { assert_module!( @@ -208,17 +122,6 @@ fn call() { ); } -#[test] -fn record_update() { - assert_module!( - r#" - fn update_name(user: User, name: ByteArray) -> User { - User { ..user, name: "Aiken", age } - } - "# - ); -} - #[test] fn record_create_labeled() { assert_module!( @@ -344,15 +247,6 @@ fn function_ambiguous_sequence() { ); } -#[test] -fn tuple_type_alias() { - assert_module!( - r#" - type RoyaltyToken = (PolicyId, AssetName) - "# - ); -} - #[test] fn first_class_binop() { assert_module!( diff --git a/crates/aiken-lang/src/tests/snapshots/anonymous_function.snap b/crates/aiken-lang/src/tests/snapshots/anonymous_function.snap deleted file mode 100644 index 93b8c216..00000000 --- a/crates/aiken-lang/src/tests/snapshots/anonymous_function.snap +++ /dev/null @@ -1,109 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\npub fn such() -> Int {\n let add_one = fn (a: Int) -> Int { a + 1 }\n\n 2 |> add_one\n}\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - Fn( - Function { - arguments: [], - body: Sequence { - location: 25..83, - expressions: [ - Assignment { - location: 25..67, - value: Fn { - location: 39..67, - fn_style: Plain, - arguments: [ - Arg { - arg_name: Named { - name: "a", - label: "a", - location: 43..44, - is_validator_param: false, - }, - location: 43..49, - annotation: Some( - Constructor { - location: 46..49, - module: None, - name: "Int", - arguments: [], - }, - ), - tipo: (), - }, - ], - body: BinOp { - location: 60..65, - name: AddInt, - left: Var { - location: 60..61, - name: "a", - }, - right: Int { - location: 64..65, - value: "1", - base: Decimal { - numeric_underscore: false, - }, - }, - }, - return_annotation: Some( - Constructor { - location: 54..57, - module: None, - name: "Int", - arguments: [], - }, - ), - }, - pattern: Var { - location: 29..36, - name: "add_one", - }, - kind: Let, - annotation: None, - }, - PipeLine { - expressions: [ - Int { - location: 71..72, - value: "2", - base: Decimal { - numeric_underscore: false, - }, - }, - Var { - location: 76..83, - name: "add_one", - }, - ], - one_liner: true, - }, - ], - }, - doc: None, - location: 0..20, - name: "such", - public: true, - return_annotation: Some( - Constructor { - location: 17..20, - module: None, - name: "Int", - arguments: [], - }, - ), - return_type: (), - end_position: 84, - can_error: true, - }, - ), - ], - kind: Validator, -} diff --git a/crates/aiken-lang/src/tests/snapshots/empty_function.snap b/crates/aiken-lang/src/tests/snapshots/empty_function.snap deleted file mode 100644 index b2c2873a..00000000 --- a/crates/aiken-lang/src/tests/snapshots/empty_function.snap +++ /dev/null @@ -1,36 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\npub fn run() {}\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - Fn( - Function { - arguments: [], - body: Trace { - kind: Todo, - location: 0..15, - then: ErrorTerm { - location: 0..15, - }, - text: String { - location: 0..15, - value: "aiken::todo", - }, - }, - doc: None, - location: 0..12, - name: "run", - public: true, - return_annotation: None, - return_type: (), - end_position: 14, - can_error: true, - }, - ), - ], - kind: Validator, -} diff --git a/crates/aiken-lang/src/tests/snapshots/fail.snap b/crates/aiken-lang/src/tests/snapshots/fail.snap deleted file mode 100644 index d983cfc7..00000000 --- a/crates/aiken-lang/src/tests/snapshots/fail.snap +++ /dev/null @@ -1,53 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\n!test invalid_inputs() {\n expect True = False\n\n False\n}\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - Test( - Function { - arguments: [], - body: Sequence { - location: 27..55, - expressions: [ - Assignment { - location: 27..46, - value: Var { - location: 41..46, - name: "False", - }, - pattern: Constructor { - is_record: false, - location: 34..38, - name: "True", - arguments: [], - module: None, - constructor: (), - with_spread: false, - tipo: (), - }, - kind: Expect, - annotation: None, - }, - Var { - location: 50..55, - name: "False", - }, - ], - }, - doc: None, - location: 0..22, - name: "invalid_inputs", - public: false, - return_annotation: None, - return_type: (), - end_position: 56, - can_error: true, - }, - ), - ], - kind: Validator, -} diff --git a/crates/aiken-lang/src/tests/snapshots/let_bindings.snap b/crates/aiken-lang/src/tests/snapshots/let_bindings.snap deleted file mode 100644 index f3ee30da..00000000 --- a/crates/aiken-lang/src/tests/snapshots/let_bindings.snap +++ /dev/null @@ -1,136 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\npub fn wow(a: Int) {\n let x =\n a + 2\n |> add_one\n |> add_one\n\n let thing = [ 1, 2, a ]\n\n let idk = thing\n\n y\n}\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - Fn( - Function { - arguments: [ - Arg { - arg_name: Named { - name: "a", - label: "a", - location: 11..12, - is_validator_param: false, - }, - location: 11..17, - annotation: Some( - Constructor { - location: 14..17, - module: None, - name: "Int", - arguments: [], - }, - ), - tipo: (), - }, - ], - body: Sequence { - location: 23..121, - expressions: [ - Assignment { - location: 23..70, - value: PipeLine { - expressions: [ - BinOp { - location: 35..40, - name: AddInt, - left: Var { - location: 35..36, - name: "a", - }, - right: Int { - location: 39..40, - value: "2", - base: Decimal { - numeric_underscore: false, - }, - }, - }, - Var { - location: 48..55, - name: "add_one", - }, - Var { - location: 63..70, - name: "add_one", - }, - ], - one_liner: false, - }, - pattern: Var { - location: 27..28, - name: "x", - }, - kind: Let, - annotation: None, - }, - Assignment { - location: 74..97, - value: List { - location: 86..97, - elements: [ - Int { - location: 88..89, - value: "1", - base: Decimal { - numeric_underscore: false, - }, - }, - Int { - location: 91..92, - value: "2", - base: Decimal { - numeric_underscore: false, - }, - }, - Var { - location: 94..95, - name: "a", - }, - ], - tail: None, - }, - pattern: Var { - location: 78..83, - name: "thing", - }, - kind: Let, - annotation: None, - }, - Assignment { - location: 101..116, - value: Var { - location: 111..116, - name: "thing", - }, - pattern: Var { - location: 105..108, - name: "idk", - }, - kind: Let, - annotation: None, - }, - Var { - location: 120..121, - name: "y", - }, - ], - }, - doc: None, - location: 0..18, - name: "wow", - public: true, - return_annotation: None, - return_type: (), - end_position: 122, - can_error: true, - }, - ), - ], - kind: Validator, -} diff --git a/crates/aiken-lang/src/tests/snapshots/pub_type_alias.snap b/crates/aiken-lang/src/tests/snapshots/pub_type_alias.snap deleted file mode 100644 index b727d5a1..00000000 --- a/crates/aiken-lang/src/tests/snapshots/pub_type_alias.snap +++ /dev/null @@ -1,35 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\npub type Me = Option\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - TypeAlias( - TypeAlias { - alias: "Me", - annotation: Constructor { - location: 14..28, - module: None, - name: "Option", - arguments: [ - Constructor { - location: 21..27, - module: None, - name: "String", - arguments: [], - }, - ], - }, - doc: None, - location: 0..28, - parameters: [], - public: true, - tipo: (), - }, - ), - ], - kind: Validator, -} diff --git a/crates/aiken-lang/src/tests/snapshots/record_update.snap b/crates/aiken-lang/src/tests/snapshots/record_update.snap deleted file mode 100644 index ce8ccca7..00000000 --- a/crates/aiken-lang/src/tests/snapshots/record_update.snap +++ /dev/null @@ -1,108 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\nfn update_name(user: User, name: ByteArray) -> User {\n User { ..user, name: \"Aiken\", age }\n}\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - Fn( - Function { - arguments: [ - Arg { - arg_name: Named { - name: "user", - label: "user", - location: 15..19, - is_validator_param: false, - }, - location: 15..25, - annotation: Some( - Constructor { - location: 21..25, - module: None, - name: "User", - arguments: [], - }, - ), - tipo: (), - }, - Arg { - arg_name: Named { - name: "name", - label: "name", - location: 27..31, - is_validator_param: false, - }, - location: 27..42, - annotation: Some( - Constructor { - location: 33..42, - module: None, - name: "ByteArray", - arguments: [], - }, - ), - tipo: (), - }, - ], - body: RecordUpdate { - location: 56..91, - constructor: Var { - location: 56..60, - name: "User", - }, - spread: RecordUpdateSpread { - base: Var { - location: 65..69, - name: "user", - }, - location: 63..69, - }, - arguments: [ - UntypedRecordUpdateArg { - label: "name", - location: 71..84, - value: ByteArray { - location: 77..84, - bytes: [ - 65, - 105, - 107, - 101, - 110, - ], - preferred_format: Utf8String, - }, - }, - UntypedRecordUpdateArg { - label: "age", - location: 86..89, - value: Var { - location: 86..89, - name: "age", - }, - }, - ], - }, - doc: None, - location: 0..51, - name: "update_name", - public: false, - return_annotation: Some( - Constructor { - location: 47..51, - module: None, - name: "User", - arguments: [], - }, - ), - return_type: (), - end_position: 92, - can_error: true, - }, - ), - ], - kind: Validator, -} diff --git a/crates/aiken-lang/src/tests/snapshots/tuple_type_alias.snap b/crates/aiken-lang/src/tests/snapshots/tuple_type_alias.snap deleted file mode 100644 index 46cf6c7c..00000000 --- a/crates/aiken-lang/src/tests/snapshots/tuple_type_alias.snap +++ /dev/null @@ -1,39 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\ntype RoyaltyToken = (PolicyId, AssetName)\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - TypeAlias( - TypeAlias { - alias: "RoyaltyToken", - annotation: Tuple { - location: 20..41, - elems: [ - Constructor { - location: 21..29, - module: None, - name: "PolicyId", - arguments: [], - }, - Constructor { - location: 31..40, - module: None, - name: "AssetName", - arguments: [], - }, - ], - }, - doc: None, - location: 0..41, - parameters: [], - public: false, - tipo: (), - }, - ), - ], - kind: Validator, -} diff --git a/crates/aiken-lang/src/tests/snapshots/type_alias.snap b/crates/aiken-lang/src/tests/snapshots/type_alias.snap deleted file mode 100644 index e86befd9..00000000 --- a/crates/aiken-lang/src/tests/snapshots/type_alias.snap +++ /dev/null @@ -1,35 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\ntype Thing = Option\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - TypeAlias( - TypeAlias { - alias: "Thing", - annotation: Constructor { - location: 13..24, - module: None, - name: "Option", - arguments: [ - Constructor { - location: 20..23, - module: None, - name: "Int", - arguments: [], - }, - ], - }, - doc: None, - location: 0..24, - parameters: [], - public: false, - tipo: (), - }, - ), - ], - kind: Validator, -} diff --git a/crates/aiken-lang/src/tests/snapshots/type_annotation_with_module_prefix.snap b/crates/aiken-lang/src/tests/snapshots/type_annotation_with_module_prefix.snap deleted file mode 100644 index bd0a3263..00000000 --- a/crates/aiken-lang/src/tests/snapshots/type_annotation_with_module_prefix.snap +++ /dev/null @@ -1,56 +0,0 @@ ---- -source: crates/aiken-lang/src/tests/parser.rs -description: "Code:\n\nuse aiken\n\npub fn go() -> aiken.Option {\n False\n}\n" ---- -Module { - name: "", - docs: [], - type_info: (), - definitions: [ - Use( - Use { - as_name: None, - location: 0..9, - module: [ - "aiken", - ], - package: (), - unqualified: [], - }, - ), - Fn( - Function { - arguments: [], - body: Var { - location: 48..53, - name: "False", - }, - doc: None, - location: 11..43, - name: "go", - public: true, - return_annotation: Some( - Constructor { - location: 26..43, - module: Some( - "aiken", - ), - name: "Option", - arguments: [ - Constructor { - location: 39..42, - module: None, - name: "Int", - arguments: [], - }, - ], - }, - ), - return_type: (), - end_position: 54, - can_error: true, - }, - ), - ], - kind: Validator, -}