test(parser): rename definitions to definition and more tests

This commit is contained in:
rvcas 2023-07-03 14:58:04 -04:00
parent baf807ca2d
commit 6b05d6a91e
No known key found for this signature in database
GPG Key ID: C09B64E263F7D68C
28 changed files with 337 additions and 362 deletions

View File

@ -1,5 +1,5 @@
mod annotation; mod annotation;
pub mod definitions; pub mod definition;
pub mod error; pub mod error;
pub mod expr; pub mod expr;
pub mod extra; pub mod extra;
@ -9,7 +9,7 @@ pub mod token;
mod utils; mod utils;
pub use annotation::parser as annotation; pub use annotation::parser as annotation;
pub use definitions::parser as definitions; pub use definition::parser as definition;
pub use expr::parser as expression; pub use expr::parser as expression;
pub use pattern::parser as pattern; pub use pattern::parser as pattern;
@ -26,7 +26,7 @@ pub fn module(
let stream = chumsky::Stream::from_iter(ast::Span::create(tokens.len()), tokens.into_iter()); let stream = chumsky::Stream::from_iter(ast::Span::create(tokens.len()), tokens.into_iter());
let definitions = definitions().parse(stream)?; let definitions = definition().repeated().then_ignore(end()).parse(stream)?;
let module = ast::UntypedModule { let module = ast::UntypedModule {
kind, kind,

View File

@ -55,3 +55,29 @@ pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError
}, },
) )
} }
#[cfg(test)]
mod tests {
use chumsky::Parser;
use crate::assert_definition;
#[test]
fn import_basic() {
assert_definition!("use aiken/list");
}
#[test]
fn import_unqualified() {
assert_definition!(
r#"
use std/address.{Address as A, thing as w}
"#
);
}
#[test]
fn import_alias() {
assert_definition!("use aiken/list as foo");
}
}

View File

@ -19,7 +19,7 @@ pub use validator::parser as validator;
use super::{error::ParseError, token::Token}; use super::{error::ParseError, token::Token};
use crate::ast; use crate::ast;
pub fn parser() -> impl Parser<Token, Vec<ast::UntypedDefinition>, Error = ParseError> { pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError> {
choice(( choice((
import(), import(),
data_type(), data_type(),
@ -29,6 +29,4 @@ pub fn parser() -> impl Parser<Token, Vec<ast::UntypedDefinition>, Error = Parse
test(), test(),
constant(), constant(),
)) ))
.repeated()
.then_ignore(end())
} }

View File

@ -0,0 +1,18 @@
---
source: crates/aiken-lang/src/parser/definition/import.rs
description: "Code:\n\nuse aiken/list as foo"
---
Use(
Use {
as_name: Some(
"foo",
),
location: 0..21,
module: [
"aiken",
"list",
],
package: (),
unqualified: [],
},
)

View File

@ -0,0 +1,16 @@
---
source: crates/aiken-lang/src/parser/definition/import.rs
description: "Code:\n\nuse aiken/list"
---
Use(
Use {
as_name: None,
location: 0..14,
module: [
"aiken",
"list",
],
package: (),
unqualified: [],
},
)

View File

@ -0,0 +1,33 @@
---
source: crates/aiken-lang/src/parser/definition/import.rs
description: "Code:\n\nuse std/address.{Address as A, thing as w}\n"
---
Use(
Use {
as_name: None,
location: 0..42,
module: [
"std",
"address",
],
package: (),
unqualified: [
UnqualifiedImport {
location: 17..29,
name: "Address",
as_name: Some(
"A",
),
layer: Value,
},
UnqualifiedImport {
location: 31..41,
name: "thing",
as_name: Some(
"w",
),
layer: Value,
},
],
},
)

View File

@ -46,3 +46,25 @@ pub fn parser<'a>(
} }
}) })
} }
#[cfg(test)]
mod tests {
use chumsky::Parser;
use crate::assert_expr;
#[test]
fn if_else_basic() {
assert_expr!(
r#"
if True {
1 + 1
} else if a < 1 {
3
} else {
4
}
"#
);
}
}

View File

@ -14,3 +14,38 @@ pub fn parser() -> impl Parser<Token, UntypedExpr, Error = ParseError> {
} }
}) })
} }
#[cfg(test)]
mod tests {
use chumsky::Parser;
use crate::assert_expr;
#[test]
fn int_literal() {
assert_expr!("1");
}
#[test]
fn int_negative() {
assert_expr!("-1");
}
#[test]
fn int_numeric_underscore() {
assert_expr!(
r#"
{
let i = 1_234_567
let j = 1_000_000
let k = -10_000
}
"#
);
}
#[test]
fn int_hex_bytes() {
assert_expr!(r#"0x01"#);
}
}

View File

@ -30,7 +30,6 @@ pub fn parser(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use chumsky::Parser; use chumsky::Parser;
use crate::assert_expr; use crate::assert_expr;

View File

@ -0,0 +1,66 @@
---
source: crates/aiken-lang/src/parser/expr/if_else.rs
description: "Code:\n\nif True {\n 1 + 1\n} else if a < 1 {\n 3\n} else {\n 4\n}\n"
---
If {
location: 0..54,
branches: [
IfBranch {
condition: Var {
location: 3..7,
name: "True",
},
body: BinOp {
location: 12..17,
name: AddInt,
left: Int {
location: 12..13,
value: "1",
base: Decimal {
numeric_underscore: false,
},
},
right: Int {
location: 16..17,
value: "1",
base: Decimal {
numeric_underscore: false,
},
},
},
location: 3..19,
},
IfBranch {
condition: BinOp {
location: 28..33,
name: LtInt,
left: Var {
location: 28..29,
name: "a",
},
right: Int {
location: 32..33,
value: "1",
base: Decimal {
numeric_underscore: false,
},
},
},
body: Int {
location: 38..39,
value: "3",
base: Decimal {
numeric_underscore: false,
},
},
location: 28..41,
},
],
final_else: Int {
location: 51..52,
value: "4",
base: Decimal {
numeric_underscore: false,
},
},
}

View File

@ -0,0 +1,9 @@
---
source: crates/aiken-lang/src/parser/expr/int.rs
description: "Code:\n\n0x01"
---
Int {
location: 0..4,
value: "1",
base: Hexadecimal,
}

View File

@ -0,0 +1,11 @@
---
source: crates/aiken-lang/src/parser/expr/int.rs
description: "Code:\n\n1"
---
Int {
location: 0..1,
value: "1",
base: Decimal {
numeric_underscore: false,
},
}

View File

@ -0,0 +1,15 @@
---
source: crates/aiken-lang/src/parser/expr/int.rs
description: "Code:\n\n-1"
---
UnOp {
op: Negate,
location: 0..2,
value: Int {
location: 1..2,
value: "1",
base: Decimal {
numeric_underscore: false,
},
},
}

View File

@ -0,0 +1,61 @@
---
source: crates/aiken-lang/src/parser/expr/int.rs
description: "Code:\n\n{\n let i = 1_234_567\n let j = 1_000_000\n let k = -10_000\n}\n"
---
Sequence {
location: 4..59,
expressions: [
Assignment {
location: 4..21,
value: Int {
location: 12..21,
value: "1234567",
base: Decimal {
numeric_underscore: true,
},
},
pattern: Var {
location: 8..9,
name: "i",
},
kind: Let,
annotation: None,
},
Assignment {
location: 24..41,
value: Int {
location: 32..41,
value: "1000000",
base: Decimal {
numeric_underscore: true,
},
},
pattern: Var {
location: 28..29,
name: "j",
},
kind: Let,
annotation: None,
},
Assignment {
location: 44..59,
value: UnOp {
op: Negate,
location: 52..59,
value: Int {
location: 53..59,
value: "10000",
base: Decimal {
numeric_underscore: true,
},
},
},
pattern: Var {
location: 48..49,
name: "k",
},
kind: Let,
annotation: None,
},
],
}

View File

@ -2,7 +2,7 @@ use chumsky::prelude::*;
use crate::{ use crate::{
ast, ast,
parser::{definitions, error::ParseError, token::Token}, parser::{definition, error::ParseError, token::Token},
}; };
pub fn parser() -> impl Parser<Token, ast::UntypedClauseGuard, Error = ParseError> { pub fn parser() -> impl Parser<Token, ast::UntypedClauseGuard, Error = ParseError> {
@ -17,7 +17,7 @@ pub fn parser() -> impl Parser<Token, ast::UntypedClauseGuard, Error = ParseErro
location: span, location: span,
}); });
let constant_parser = definitions::constant::value().map(ast::ClauseGuard::Constant); let constant_parser = definition::constant::value().map(ast::ClauseGuard::Constant);
let block_parser = r let block_parser = r
.clone() .clone()

View File

@ -128,3 +128,22 @@ macro_rules! assert_module {
}); });
}; };
} }
#[macro_export]
macro_rules! assert_definition {
($code:expr) => {
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::definition().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);
});
};
}

View File

@ -72,24 +72,6 @@ fn double_validator() {
); );
} }
#[test]
fn import() {
assert_module!(
r#"
use std/list
"#
);
}
#[test]
fn unqualified_imports() {
assert_module!(
r#"
use std/address.{Address as A, thing as w}
"#
);
}
#[test] #[test]
fn import_alias() { fn import_alias() {
assert_module!( assert_module!(
@ -186,25 +168,6 @@ fn pipeline() {
); );
} }
#[test]
fn if_expression() {
assert_module!(
r#"
fn ifs() {
if True {
1 + 1
} else if a < 4 {
5
} else if a || b {
6
} else {
3
}
}
"#
);
}
#[test] #[test]
fn let_bindings() { fn let_bindings() {
assert_module!( assert_module!(
@ -445,30 +408,6 @@ fn tuple_type_alias() {
); );
} }
#[test]
fn int_parsing_hex_bytes() {
assert_module!(
r#"
fn foo() {
#[ 0x01, 0xa2, 0x03 ]
}
"#
);
}
#[test]
fn test_parsing_numeric_underscore() {
assert_module!(
r#"
fn foo() {
let i = 1_234_567
let j = 1_000_000
let k = -10_000
}
"#
);
}
#[test] #[test]
fn first_class_binop() { fn first_class_binop() {
assert_module!( assert_module!(

View File

@ -1,109 +0,0 @@
---
source: crates/aiken-lang/src/tests/parser.rs
description: "Code:\n\nfn ifs() {\n if True {\n 1 + 1\n } else if a < 4 {\n 5\n } else if a || b {\n 6\n } else {\n 3\n }\n}\n"
---
Module {
name: "",
docs: [],
type_info: (),
definitions: [
Fn(
Function {
arguments: [],
body: If {
location: 13..106,
branches: [
IfBranch {
condition: Var {
location: 16..20,
name: "True",
},
body: BinOp {
location: 27..32,
name: AddInt,
left: Int {
location: 27..28,
value: "1",
base: Decimal {
numeric_underscore: false,
},
},
right: Int {
location: 31..32,
value: "1",
base: Decimal {
numeric_underscore: false,
},
},
},
location: 16..36,
},
IfBranch {
condition: BinOp {
location: 45..50,
name: LtInt,
left: Var {
location: 45..46,
name: "a",
},
right: Int {
location: 49..50,
value: "4",
base: Decimal {
numeric_underscore: false,
},
},
},
body: Int {
location: 57..58,
value: "5",
base: Decimal {
numeric_underscore: false,
},
},
location: 45..62,
},
IfBranch {
condition: BinOp {
location: 71..77,
name: Or,
left: Var {
location: 71..72,
name: "a",
},
right: Var {
location: 76..77,
name: "b",
},
},
body: Int {
location: 84..85,
value: "6",
base: Decimal {
numeric_underscore: false,
},
},
location: 71..89,
},
],
final_else: Int {
location: 101..102,
value: "3",
base: Decimal {
numeric_underscore: false,
},
},
},
doc: None,
location: 0..8,
name: "ifs",
public: false,
return_annotation: None,
return_type: (),
end_position: 107,
can_error: true,
},
),
],
kind: Validator,
}

View File

@ -1,24 +0,0 @@
---
source: crates/aiken-lang/src/tests/parser.rs
description: "Code:\n\nuse std/list\n"
---
Module {
name: "",
docs: [],
type_info: (),
definitions: [
Use(
Use {
as_name: None,
location: 0..12,
module: [
"std",
"list",
],
package: (),
unqualified: [],
},
),
],
kind: Validator,
}

View File

@ -1,36 +0,0 @@
---
source: crates/aiken-lang/src/tests/parser.rs
description: "Code:\n\nfn foo() {\n #[ 0x01, 0xa2, 0x03 ]\n}\n"
---
Module {
name: "",
docs: [],
type_info: (),
definitions: [
Fn(
Function {
arguments: [],
body: ByteArray {
location: 13..34,
bytes: [
1,
162,
3,
],
preferred_format: ArrayOfBytes(
Hexadecimal,
),
},
doc: None,
location: 0..8,
name: "foo",
public: false,
return_annotation: None,
return_type: (),
end_position: 35,
can_error: true,
},
),
],
kind: Validator,
}

View File

@ -1,82 +0,0 @@
---
source: crates/aiken-lang/src/tests/parser.rs
description: "Code:\n\nfn foo() {\n let i = 1_234_567\n let j = 1_000_000\n let k = -10_000\n}\n"
---
Module {
name: "",
docs: [],
type_info: (),
definitions: [
Fn(
Function {
arguments: [],
body: Sequence {
location: 13..68,
expressions: [
Assignment {
location: 13..30,
value: Int {
location: 21..30,
value: "1234567",
base: Decimal {
numeric_underscore: true,
},
},
pattern: Var {
location: 17..18,
name: "i",
},
kind: Let,
annotation: None,
},
Assignment {
location: 33..50,
value: Int {
location: 41..50,
value: "1000000",
base: Decimal {
numeric_underscore: true,
},
},
pattern: Var {
location: 37..38,
name: "j",
},
kind: Let,
annotation: None,
},
Assignment {
location: 53..68,
value: UnOp {
op: Negate,
location: 61..68,
value: Int {
location: 62..68,
value: "10000",
base: Decimal {
numeric_underscore: true,
},
},
},
pattern: Var {
location: 57..58,
name: "k",
},
kind: Let,
annotation: None,
},
],
},
doc: None,
location: 0..8,
name: "foo",
public: false,
return_annotation: None,
return_type: (),
end_position: 69,
can_error: true,
},
),
],
kind: Validator,
}

View File

@ -1,41 +0,0 @@
---
source: crates/aiken-lang/src/tests/parser.rs
description: "Code:\n\nuse std/address.{Address as A, thing as w}\n"
---
Module {
name: "",
docs: [],
type_info: (),
definitions: [
Use(
Use {
as_name: None,
location: 0..42,
module: [
"std",
"address",
],
package: (),
unqualified: [
UnqualifiedImport {
location: 17..29,
name: "Address",
as_name: Some(
"A",
),
layer: Value,
},
UnqualifiedImport {
location: 31..41,
name: "thing",
as_name: Some(
"w",
),
layer: Value,
},
],
},
),
],
kind: Validator,
}