schala/schala-lang/language/src/parsing/test.rs

710 lines
24 KiB
Rust
Raw Normal View History

#![cfg(test)]
use ::std::rc::Rc;
use std::str::FromStr;
use super::tokenize;
use super::ParseResult;
2019-09-18 09:56:11 -07:00
use crate::ast::{ItemIdStore, AST, Meta, Expression, Statement, StatementKind, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument, FormalParam, PrefixOp, BinOp, QualifiedName};
use super::Declaration::*;
use super::Signature;
use super::TypeIdentifier::*;
use super::TypeSingletonName;
use super::ExpressionKind::*;
use super::Variant::*;
use super::ForBody::*;
fn parse(input: &str) -> ParseResult<AST> {
let tokens: Vec<crate::tokenizing::Token> = tokenize(input);
let mut parser = super::Parser::new(tokens);
parser.parse()
}
macro_rules! parse_test {
2019-09-18 09:56:11 -07:00
($string:expr, $correct:expr) => {
2019-09-18 01:58:38 -07:00
assert_eq!(parse($string).unwrap(), $correct)
};
}
macro_rules! parse_test_wrap_ast {
2019-09-18 09:56:11 -07:00
($string:expr, $correct:expr) => { parse_test!($string, AST { id: ItemIdStore::new_id(), statements: vec![$correct] }) }
}
macro_rules! parse_error {
($string:expr) => { assert!(parse($string).is_err()) }
}
2019-09-19 01:34:21 -07:00
macro_rules! qname {
( $( $component:expr),* ) => {
{
let mut components = vec![];
$(
components.push(rc!($component));
)*
QualifiedName { components, id: ItemIdStore::new_id() }
}
};
}
macro_rules! val {
2019-09-20 01:57:48 -07:00
($var:expr) => { Value(QualifiedName { components: vec![Rc::new($var.to_string())], id: ItemIdStore::new_id() }) };
}
macro_rules! ty {
($name:expr) => { Singleton(tys!($name)) }
}
macro_rules! tys {
($name:expr) => { TypeSingletonName { name: Rc::new($name.to_string()), params: vec![] } };
}
2019-09-17 02:25:11 -07:00
macro_rules! decl {
($expr_type:expr) => {
2019-09-18 10:07:20 -07:00
Statement { id: ItemIdStore::new_id(), kind: StatementKind::Declaration($expr_type) }
2019-09-17 02:25:11 -07:00
};
}
macro_rules! ex {
2019-09-18 14:15:05 -07:00
($expr_type:expr) => { Expression::new(ItemIdStore::new_id(), $expr_type) };
(m $expr_type:expr) => { Meta::new(Expression::new(ItemIdStore::new_id(), $expr_type)) };
(m $expr_type:expr, $type_anno:expr) => { Meta::new(Expression::with_anno(ItemIdStore::new_id(), $expr_type, $type_anno)) };
(s $expr_text:expr) => {
{
let tokens: Vec<crate::tokenizing::Token> = tokenize($expr_text);
let mut parser = super::Parser::new(tokens);
parser.expression().unwrap()
}
};
}
macro_rules! inv {
($expr_type:expr) => { InvocationArgument::Positional($expr_type) }
}
macro_rules! binexp {
2019-09-18 14:15:05 -07:00
($op:expr, $lhs:expr, $rhs:expr) => { BinExp(BinOp::from_sigil($op), bx!(Expression::new(ItemIdStore::new_id(), $lhs).into()), bx!(Expression::new(ItemIdStore::new_id(), $rhs).into())) }
}
macro_rules! prefexp {
2019-09-18 14:15:05 -07:00
($op:expr, $lhs:expr) => { PrefixExp(PrefixOp::from_str($op).unwrap(), bx!(Expression::new(ItemIdStore::new_id(), $lhs).into())) }
}
macro_rules! exst {
2019-09-18 14:15:05 -07:00
($expr_type:expr) => { Meta::new(Statement { id: ItemIdStore::new_id(), kind: StatementKind::Expression(Expression::new(ItemIdStore::new_id(), $expr_type).into())}) };
($expr_type:expr, $type_anno:expr) => { Meta::new(Statement { id: ItemIdStore::new_id(), kind: StatementKind::Expression(Expression::with_anno(ItemIdStore::new_id(), $expr_type, $type_anno).into())}) };
2019-09-17 02:25:11 -07:00
($op:expr, $lhs:expr, $rhs:expr) => { Meta::new(
2019-09-18 10:07:20 -07:00
Statement { id: ItemIdStore::new_id(), ,kind: StatementKind::Expression(ex!(binexp!($op, $lhs, $rhs)))}
2019-09-17 02:25:11 -07:00
)};
(s $statement_text:expr) => {
{
let tokens: Vec<crate::tokenizing::Token> = tokenize($statement_text);
let mut parser = super::Parser::new(tokens);
Meta::new(parser.statement().unwrap())
}
}
}
#[test]
fn parsing_number_literals_and_binexps() {
parse_test_wrap_ast! { ".2", exst!(FloatLiteral(0.2)) };
parse_test_wrap_ast! { "8.1", exst!(FloatLiteral(8.1)) };
parse_test_wrap_ast! { "0b010", exst!(NatLiteral(2)) };
parse_test_wrap_ast! { "0b0_1_0_", exst!(NatLiteral(2)) }
parse_test_wrap_ast! {"0xff", exst!(NatLiteral(255)) };
parse_test_wrap_ast! {"0xf_f_", exst!(NatLiteral(255)) };
parse_test_wrap_ast! {"0xf_f_+1", exst!(binexp!("+", NatLiteral(255), NatLiteral(1))) };
2019-09-11 19:06:00 -07:00
parse_test! {"3; 4; 4.3",
AST {
2019-09-18 09:56:11 -07:00
id: ItemIdStore::new_id(),
2019-09-11 19:06:00 -07:00
statements: vec![exst!(NatLiteral(3)), exst!(NatLiteral(4)),
exst!(FloatLiteral(4.3))]
}
};
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("1 + 2 * 3",
exst!(binexp!("+", NatLiteral(1), binexp!("*", NatLiteral(2), NatLiteral(3))))
);
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("1 * 2 + 3",
exst!(binexp!("+", binexp!("*", NatLiteral(1), NatLiteral(2)), NatLiteral(3)))
) ;
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("1 && 2", exst!(binexp!("&&", NatLiteral(1), NatLiteral(2))));
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("1 + 2 * 3 + 4", exst!(
binexp!("+",
binexp!("+", NatLiteral(1), binexp!("*", NatLiteral(2), NatLiteral(3))),
2019-09-11 19:06:00 -07:00
NatLiteral(4))));
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("(1 + 2) * 3",
exst!(binexp!("*", binexp!("+", NatLiteral(1), NatLiteral(2)), NatLiteral(3))));
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!(".1 + .2", exst!(binexp!("+", FloatLiteral(0.1), FloatLiteral(0.2))));
parse_test_wrap_ast!("1 / 2", exst!(binexp!("/", NatLiteral(1), NatLiteral(2))));
}
#[test]
fn parsing_tuples() {
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("()", exst!(TupleLiteral(vec![])));
parse_test_wrap_ast!("(\"hella\", 34)", exst!(
TupleLiteral(
vec![ex!(s r#""hella""#).into(), ex!(s "34").into()]
)
2019-09-11 19:06:00 -07:00
));
parse_test_wrap_ast!("((1+2), \"slough\")", exst!(TupleLiteral(vec![
ex!(binexp!("+", NatLiteral(1), NatLiteral(2))).into(),
ex!(StringLiteral(rc!(slough))).into(),
2019-09-11 19:06:00 -07:00
])))
}
#[test]
fn parsing_identifiers() {
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("a", exst!(val!("a")));
parse_test_wrap_ast!("some_value", exst!(val!("some_value")));
parse_test_wrap_ast!("a + b", exst!(binexp!("+", val!("a"), val!("b"))));
//parse_test!("a[b]", AST(vec![Expression(
//parse_test!("a[]", <- TODO THIS NEEDS TO FAIL
//parse_test("a()[b]()[d]")
//TODO fix this parsing stuff
/*
parse_test! { "perspicacity()[a]", AST(vec![
exst!(Index {
indexee: bx!(ex!(Call { f: bx!(ex!(val!("perspicacity"))), arguments: vec![] })),
indexers: vec![ex!(val!("a"))]
})
2019-09-11 19:06:00 -07:00
])
}
*/
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("a[b,c]", exst!(Index { indexee: bx!(ex!(m val!("a"))), indexers: vec![ex!(m val!("b")), ex!(m val!("c"))]} ));
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("None", exst!(val!("None")));
parse_test_wrap_ast!("Pandas { a: x + y }",
2019-09-19 01:34:21 -07:00
exst!(NamedStruct { name: Meta::new(qname!(Pandas)), fields: vec![(rc!(a), ex!(m binexp!("+", val!("x"), val!("y"))))]})
2019-09-11 19:06:00 -07:00
);
parse_test_wrap_ast! { "Pandas { a: n, b: q, }",
2019-09-19 01:34:21 -07:00
exst!(NamedStruct { name: Meta::new(qname!(Pandas)), fields:
2019-09-11 19:06:00 -07:00
vec![(rc!(a), ex!(m val!("n"))), (rc!(b), ex!(m val!("q")))]
}
)
};
}
2019-09-01 01:07:00 -07:00
#[test]
fn qualified_identifiers() {
parse_test_wrap_ast! {
"let q_q = Yolo::Swaggins",
2019-09-17 02:25:11 -07:00
Meta::new(decl!(Binding { name: rc!(q_q), constant: true, type_anno: None,
2019-09-20 01:57:48 -07:00
expr: Meta::new(Expression::new(ItemIdStore::new_id(), Value(qname!(Yolo, Swaggins)))),
2019-09-01 01:07:00 -07:00
}))
}
parse_test_wrap_ast! {
"thing::item::call()",
2019-09-20 01:57:48 -07:00
exst!(Call { f: bx![ex!(m Value(qname!(thing, item, call)))], arguments: vec![] })
2019-09-01 01:07:00 -07:00
}
}
#[test]
fn reserved_words() {
parse_error!("module::item::call()");
}
#[test]
fn parsing_complicated_operators() {
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("a <- b", exst!(binexp!("<-", val!("a"), val!("b"))));
parse_test_wrap_ast!("a || b", exst!(binexp!("||", val!("a"), val!("b"))));
parse_test_wrap_ast!("a<>b", exst!(binexp!("<>", val!("a"), val!("b"))));
parse_test_wrap_ast!("a.b.c.d", exst!(binexp!(".",
binexp!(".",
binexp!(".", val!("a"), val!("b")),
val!("c")),
2019-09-11 19:06:00 -07:00
val!("d"))));
parse_test_wrap_ast!("-3", exst!(prefexp!("-", NatLiteral(3))));
parse_test_wrap_ast!("-0.2", exst!(prefexp!("-", FloatLiteral(0.2))));
parse_test_wrap_ast!("!3", exst!(prefexp!("!", NatLiteral(3))));
parse_test_wrap_ast!("a <- -b", exst!(binexp!("<-", val!("a"), prefexp!("-", val!("b")))));
parse_test_wrap_ast!("a <--b", exst!(binexp!("<--", val!("a"), val!("b"))));
}
#[test]
fn parsing_functions() {
2019-09-17 02:25:11 -07:00
parse_test_wrap_ast!("fn oi()", Meta::new(decl!(FuncSig(Signature { name: rc!(oi), operator: false, params: vec![], type_anno: None }))));
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("oi()", exst!(Call { f: bx!(ex!(m val!("oi"))), arguments: vec![] }));
parse_test_wrap_ast!("oi(a, 2 + 2)", exst!(Call
{ f: bx!(ex!(m val!("oi"))),
arguments: vec![inv!(ex!(m val!("a"))), inv!(ex!(m binexp!("+", NatLiteral(2), NatLiteral(2)))).into()]
2019-09-11 19:06:00 -07:00
}));
parse_error!("a(b,,c)");
2019-09-17 02:25:11 -07:00
parse_test_wrap_ast!("fn a(b, c: Int): Int", Meta::new(decl!(
FuncSig(Signature { name: rc!(a), operator: false, params: vec![
FormalParam { name: rc!(b), anno: None, default: None },
FormalParam { name: rc!(c), anno: Some(ty!("Int")), default: None }
2019-09-11 19:06:00 -07:00
], type_anno: Some(ty!("Int")) }))));
2019-09-17 02:25:11 -07:00
parse_test_wrap_ast!("fn a(x) { x() }", Meta::new(decl!(
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), anno: None, default: None }], type_anno: None },
2019-09-11 19:06:00 -07:00
vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })]))));
2019-09-17 02:25:11 -07:00
parse_test_wrap_ast!("fn a(x) {\n x() }", Meta::new(decl!(
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), anno: None, default: None }], type_anno: None },
2019-09-11 19:06:00 -07:00
vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })]))));
let multiline = r#"
fn a(x) {
x()
}
"#;
2019-09-17 02:25:11 -07:00
parse_test_wrap_ast!(multiline, Meta::new(decl!(
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), default: None, anno: None }], type_anno: None },
2019-09-11 19:06:00 -07:00
vec![exst!(Call { f: bx!(ex!(m val!("x"))), arguments: vec![] })]))));
let multiline2 = r#"
fn a(x) {
x()
}
"#;
2019-09-17 02:25:11 -07:00
parse_test_wrap_ast!(multiline2, Meta::new(decl!(
FuncDecl(Signature { name: rc!(a), operator: false, params: vec![FormalParam { name: rc!(x), default: None, anno: None }], type_anno: None },
2019-09-11 19:06:00 -07:00
vec![exst!(s "x()")]))));
}
2019-06-16 21:36:59 -07:00
#[test]
fn functions_with_default_args() {
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast! {
2019-06-16 21:36:59 -07:00
"fn func(x: Int, y: Int = 4) { }",
2019-09-17 02:25:11 -07:00
Meta::new(decl!(
2019-09-11 19:06:00 -07:00
FuncDecl(Signature { name: rc!(func), operator: false, type_anno: None, params: vec![
FormalParam { name: rc!(x), default: None, anno: Some(ty!("Int")) },
FormalParam { name: rc!(y), default: Some(Meta::new(ex!(s "4"))), anno: Some(ty!("Int")) }
]}, vec![])
))
2019-06-16 21:36:59 -07:00
};
}
#[test]
fn parsing_bools() {
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("false", exst!(BoolLiteral(false)));
parse_test_wrap_ast!("true", exst!(BoolLiteral(true)));
}
#[test]
fn parsing_strings() {
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!(r#""hello""#, exst!(StringLiteral(rc!(hello))));
}
#[test]
fn parsing_types() {
2019-09-17 02:25:11 -07:00
parse_test_wrap_ast!("type Yolo = Yolo", Meta::new(decl!(TypeDecl { name: tys!("Yolo"), body: TypeBody(vec![UnitStruct(rc!(Yolo))]), mutable: false} )));
parse_test_wrap_ast!("type mut Yolo = Yolo", Meta::new(decl!(TypeDecl { name: tys!("Yolo"), body: TypeBody(vec![UnitStruct(rc!(Yolo))]), mutable: true} )));
parse_test_wrap_ast!("type alias Sex = Drugs", Meta::new(decl!(TypeAlias(rc!(Sex), rc!(Drugs)))));
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("type Sanchez = Miguel | Alejandro(Int, Option<a>) | Esperanza { a: Int, b: String }",
2019-09-17 02:25:11 -07:00
Meta::new(decl!(TypeDecl {
name: tys!("Sanchez"),
body: TypeBody(vec![
UnitStruct(rc!(Miguel)),
TupleStruct(rc!(Alejandro), vec![
Singleton(TypeSingletonName { name: rc!(Int), params: vec![] }),
Singleton(TypeSingletonName { name: rc!(Option), params: vec![Singleton(TypeSingletonName { name: rc!(a), params: vec![] })] }),
]),
Record{
name: rc!(Esperanza),
members: vec![
(rc!(a), Singleton(TypeSingletonName { name: rc!(Int), params: vec![] })),
(rc!(b), Singleton(TypeSingletonName { name: rc!(String), params: vec![] })),
]
}
]),
mutable: false
2019-09-11 19:06:00 -07:00
})));
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast! {
"type Jorge<a> = Diego | Kike(a)",
2019-09-17 02:25:11 -07:00
Meta::new(decl!(TypeDecl{
name: TypeSingletonName { name: rc!(Jorge), params: vec![Singleton(TypeSingletonName { name: rc!(a), params: vec![] })] },
body: TypeBody(vec![UnitStruct(rc!(Diego)), TupleStruct(rc!(Kike), vec![Singleton(TypeSingletonName { name: rc!(a), params: vec![] })])]),
mutable: false
}
2019-09-11 19:06:00 -07:00
))
};
}
#[test]
fn parsing_bindings() {
2019-09-17 02:25:11 -07:00
parse_test_wrap_ast!("let mut a = 10", Meta::new(decl!(Binding { name: rc!(a), constant: false, type_anno: None, expr: ex!(m NatLiteral(10)) } )));
parse_test_wrap_ast!("let a = 2 + 2", Meta::new(decl!(Binding { name: rc!(a), constant: true, type_anno: None, expr: ex!(m binexp!("+", NatLiteral(2), NatLiteral(2))) }) ));
parse_test_wrap_ast!("let a: Nat = 2 + 2", Meta::new(decl!(
Binding { name: rc!(a), constant: true, type_anno: Some(Singleton(TypeSingletonName { name: rc!(Nat), params: vec![] })),
expr: Meta::new(ex!(binexp!("+", NatLiteral(2), NatLiteral(2)))) }
2019-09-11 19:06:00 -07:00
)));
}
#[test]
fn parsing_block_expressions() {
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast! {
"if a() then { b(); c() }", exst!(
IfExpression {
discriminator: bx! {
2019-09-02 14:13:53 -07:00
Discriminator::Simple(ex!(m Call { f: bx!(ex!(m val!("a"))), arguments: vec![]}))
},
body: bx! {
IfExpressionBody::SimpleConditional(
vec![exst!(Call { f: bx!(ex!(m val!("b"))), arguments: vec![]}), exst!(Call { f: bx!(ex!(m val!("c"))), arguments: vec![] })],
None
)
}
}
2019-09-11 19:06:00 -07:00
)
};
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast! {
"if a() then { b(); c() } else { q }", exst!(
IfExpression {
discriminator: bx! {
2019-09-02 14:13:53 -07:00
Discriminator::Simple(ex!(m Call { f: bx!(ex!(m val!("a"))), arguments: vec![]}))
},
body: bx! {
IfExpressionBody::SimpleConditional(
vec![exst!(Call { f: bx!(ex!(m val!("b"))), arguments: vec![]}), exst!(Call { f: bx!(ex!(m val!("c"))), arguments: vec![] })],
Some(
vec![exst!(val!("q"))],
)
)
}
}
2019-09-11 19:06:00 -07:00
)
};
/*
parse_test!("if a() then { b(); c() }", AST(vec![exst!(
IfExpression(bx!(ex!(Call { f: bx!(ex!(val!("a"))), arguments: vec![]})),
vec![exst!(Call { f: bx!(ex!(val!("b"))), arguments: vec![]}), exst!(Call { f: bx!(ex!(val!("c"))), arguments: vec![] })],
None)
)]));
parse_test!(r#"
if true then {
const a = 10
b
} else {
c
}"#,
AST(vec![exst!(IfExpression(bx!(ex!(BoolLiteral(true))),
2019-09-17 02:25:11 -07:00
vec![decl!(Binding { name: rc!(a), constant: true, expr: ex!(NatLiteral(10)) }),
exst!(val!(rc!(b)))],
Some(vec![exst!(val!(rc!(c)))])))])
);
parse_test!("if a { b } else { c }", AST(vec![exst!(
IfExpression(bx!(ex!(val!("a"))),
vec![exst!(val!("b"))],
Some(vec![exst!(val!("c"))])))]));
parse_test!("if (A {a: 1}) { b } else { c }", AST(vec![exst!(
IfExpression(bx!(ex!(NamedStruct { name: rc!(A), fields: vec![(rc!(a), ex!(NatLiteral(1)))]})),
vec![exst!(val!("b"))],
Some(vec![exst!(val!("c"))])))]));
parse_error!("if A {a: 1} { b } else { c }");
*/
}
#[test]
fn parsing_interfaces() {
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("interface Unglueable { fn unglue(a: Glue); fn mar(): Glue }",
2019-09-17 02:25:11 -07:00
Meta::new(decl!(Interface {
name: rc!(Unglueable),
signatures: vec![
Signature {
name: rc!(unglue),
operator: false,
params: vec![
FormalParam { name: rc!(a), anno: Some(Singleton(TypeSingletonName { name: rc!(Glue), params: vec![] })), default: None }
],
type_anno: None
},
Signature { name: rc!(mar), operator: false, params: vec![], type_anno: Some(Singleton(TypeSingletonName { name: rc!(Glue), params: vec![] })) },
]
}))
2019-09-11 19:06:00 -07:00
);
}
#[test]
fn parsing_impls() {
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("impl Heh { fn yolo(); fn swagg(); }",
Meta::new(
2019-09-17 02:25:11 -07:00
decl!(Impl {
type_name: ty!("Heh"),
interface_name: None,
block: vec![
FuncSig(Signature { name: rc!(yolo), operator: false, params: vec![], type_anno: None }),
FuncSig(Signature { name: rc!(swagg), operator: false, params: vec![], type_anno: None })
2019-09-11 19:06:00 -07:00
] })));
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("impl Mondai for Lollerino { fn yolo(); fn swagg(); }",
2019-09-17 02:25:11 -07:00
Meta::new(decl!(Impl {
type_name: ty!("Lollerino"),
interface_name: Some(TypeSingletonName { name: rc!(Mondai), params: vec![] }),
block: vec![
FuncSig(Signature { name: rc!(yolo), operator: false, params: vec![], type_anno: None}),
FuncSig(Signature { name: rc!(swagg), operator: false, params: vec![], type_anno: None })
2019-09-11 19:06:00 -07:00
] })));
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("impl Hella<T> for (Alpha, Omega) { }",
2019-09-17 02:25:11 -07:00
Meta::new(decl!(Impl {
type_name: Tuple(vec![ty!("Alpha"), ty!("Omega")]),
interface_name: Some(TypeSingletonName { name: rc!(Hella), params: vec![ty!("T")] }),
block: vec![]
}))
2019-09-11 19:06:00 -07:00
);
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("impl Option<WTFMate> { fn oi() }",
Meta::new(
2019-09-17 02:25:11 -07:00
decl!(Impl {
type_name: Singleton(TypeSingletonName { name: rc!(Option), params: vec![ty!("WTFMate")]}),
interface_name: None,
block: vec![
FuncSig(Signature { name: rc!(oi), operator: false, params: vec![], type_anno: None }),
]
2019-09-11 19:06:00 -07:00
})));
}
#[test]
fn parsing_type_annotations() {
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("let a = b : Int",
Meta::new(
2019-09-17 02:25:11 -07:00
decl!(Binding { name: rc!(a), constant: true, type_anno: None, expr:
2019-09-11 19:06:00 -07:00
ex!(m val!("b"), ty!("Int")) })));
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("a : Int",
exst!(val!("a"), ty!("Int"))
2019-09-11 19:06:00 -07:00
);
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("a : Option<Int>",
exst!(val!("a"), Singleton(TypeSingletonName { name: rc!(Option), params: vec![ty!("Int")] }))
2019-09-11 19:06:00 -07:00
);
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("a : KoreanBBQSpecifier<Kimchi, Option<Bulgogi> >",
exst!(val!("a"), Singleton(TypeSingletonName { name: rc!(KoreanBBQSpecifier), params: vec![
ty!("Kimchi"), Singleton(TypeSingletonName { name: rc!(Option), params: vec![ty!("Bulgogi")] })
] }))
2019-09-11 19:06:00 -07:00
);
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!("a : (Int, Yolo<a>)",
exst!(val!("a"), Tuple(
vec![ty!("Int"), Singleton(TypeSingletonName {
name: rc!(Yolo), params: vec![ty!("a")]
2019-09-11 19:06:00 -07:00
})])));
}
#[test]
fn parsing_lambdas() {
parse_test_wrap_ast! { r#"\(x) { x + 1}"#, exst!(
Lambda { params: vec![FormalParam { name: rc!(x), anno: None, default: None } ], type_anno: None, body: vec![exst!(s "x + 1")] }
)
}
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast!(r#"\ (x: Int, y) { a;b;c;}"#,
exst!(Lambda {
params: vec![
FormalParam { name: rc!(x), anno: Some(ty!("Int")), default: None },
FormalParam { name: rc!(y), anno: None, default: None }
],
type_anno: None,
body: vec![exst!(s "a"), exst!(s "b"), exst!(s "c")]
})
2019-09-11 19:06:00 -07:00
);
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast! { r#"\(x){y}(1)"#,
exst!(Call { f: bx!(ex!(m
Lambda {
params: vec![
FormalParam { name: rc!(x), anno: None, default: None }
],
type_anno: None,
body: vec![exst!(s "y")] }
)),
2019-09-11 19:06:00 -07:00
arguments: vec![inv!(ex!(m NatLiteral(1))).into()] })
};
parse_test_wrap_ast! {
r#"\(x: Int): String { "q" }"#,
exst!(Lambda {
params: vec![
FormalParam { name: rc!(x), anno: Some(ty!("Int")), default: None },
],
type_anno: Some(ty!("String")),
body: vec![exst!(s r#""q""#)]
})
}
}
#[test]
fn single_param_lambda() {
parse_test_wrap_ast! {
r"\x { x + 10 }",
exst!(Lambda {
params: vec![FormalParam { name: rc!(x), anno: None, default: None }],
type_anno: None,
body: vec![exst!(s r"x + 10")]
})
}
parse_test_wrap_ast! {
r"\x: Nat { x + 10 }",
exst!(Lambda {
params: vec![FormalParam { name: rc!(x), anno: Some(ty!("Nat")), default: None }],
type_anno: None,
body: vec![exst!(s r"x + 10")]
})
}
}
#[test]
fn more_advanced_lambdas() {
parse_test! {
r#"fn wahoo() { let a = 10; \(x) { x + a } };
2019-09-11 19:06:00 -07:00
wahoo()(3) "#,
AST {
2019-09-18 09:56:11 -07:00
id: ItemIdStore::new_id(),
2019-09-11 19:06:00 -07:00
statements: vec![
exst!(s r"fn wahoo() { let a = 10; \(x) { x + a } }"),
exst! {
Call {
f: bx!(ex!(m Call { f: bx!(ex!(m val!("wahoo"))), arguments: vec![] })),
2019-09-02 14:13:53 -07:00
arguments: vec![inv!(ex!(m NatLiteral(3))).into()],
}
}
2019-09-11 19:06:00 -07:00
]
}
}
}
#[test]
fn list_literals() {
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast! {
"[1,2]",
exst!(ListLiteral(vec![ex!(m NatLiteral(1)), ex!(m NatLiteral(2))]))
};
}
#[test]
fn while_expr() {
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast! {
"while { }",
exst!(WhileExpression { condition: None, body: vec![] })
}
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast! {
"while a == b { }",
exst!(WhileExpression { condition: Some(bx![ex![m binexp!("==", val!("a"), val!("b"))]]), body: vec![] })
}
}
#[test]
fn for_expr() {
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast! {
"for { a <- maybeValue } return 1",
exst!(ForExpression {
enumerators: vec![Enumerator { id: rc!(a), generator: ex!(m val!("maybeValue")) }],
body: bx!(MonadicReturn(Meta::new(ex!(s "1"))))
2019-09-11 19:06:00 -07:00
})
}
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast! {
"for n <- someRange { f(n); }",
exst!(ForExpression { enumerators: vec![Enumerator { id: rc!(n), generator: ex!(m val!("someRange"))}],
body: bx!(ForBody::StatementBlock(vec![exst!(s "f(n)")]))
2019-09-11 19:06:00 -07:00
})
}
}
#[test]
fn patterns() {
parse_test_wrap_ast! {
"if x is Some(a) then { 4 } else { 9 }", exst!(
IfExpression {
2019-09-02 14:13:53 -07:00
discriminator: bx!(Discriminator::Simple(Meta::new(ex!(s "x")))),
2019-09-20 02:03:10 -07:00
body: bx!(IfExpressionBody::SimplePatternMatch(Pattern::TupleStruct(qname!(Some),
vec![Pattern::VarOrName(qname!(a))]), vec![exst!(s "4")], Some(vec![exst!(s "9")]))) }
)
}
parse_test_wrap_ast! {
"if x is Some(a) then 4 else 9", exst!(
IfExpression {
2019-09-02 14:13:53 -07:00
discriminator: bx!(Discriminator::Simple(Meta::new(ex!(s "x")))),
2019-09-20 02:03:10 -07:00
body: bx!(IfExpressionBody::SimplePatternMatch(Pattern::TupleStruct(qname!(Some),
vec![Pattern::VarOrName(qname!(a))]), vec![exst!(s "4")], Some(vec![exst!(s "9")]))) }
)
}
parse_test_wrap_ast! {
"if x is Something { a, b: x } then { 4 } else { 9 }", exst!(
IfExpression {
2019-09-02 14:13:53 -07:00
discriminator: bx!(Discriminator::Simple(Meta::new(ex!(s "x")))),
body: bx!(IfExpressionBody::SimplePatternMatch(
2019-09-20 02:03:10 -07:00
Pattern::Record(qname!(Something), vec![
(rc!(a),Pattern::Literal(PatternLiteral::StringPattern(rc!(a)))),
2019-09-20 02:03:10 -07:00
(rc!(b),Pattern::VarOrName(qname!(x)))
]),
2019-09-06 02:30:18 -07:00
vec![exst!(s "4")], Some(vec![exst!(s "9")])))
}
)
}
}
#[test]
fn pattern_literals() {
parse_test_wrap_ast! {
"if x is -1 then 1 else 2",
exst!(
IfExpression {
2019-09-02 14:13:53 -07:00
discriminator: bx!(Discriminator::Simple(Meta::new(ex!(s "x")))),
body: bx!(IfExpressionBody::SimplePatternMatch(
Pattern::Literal(PatternLiteral::NumPattern { neg: true, num: NatLiteral(1) }),
vec![exst!(NatLiteral(1))],
Some(vec![exst!(NatLiteral(2))]),
))
}
)
}
parse_test_wrap_ast! {
"if x is 1 then 1 else 2",
exst!(
IfExpression {
2019-09-02 14:13:53 -07:00
discriminator: bx!(Discriminator::Simple(Meta::new(ex!(s "x")))),
body: bx!(IfExpressionBody::SimplePatternMatch(
Pattern::Literal(PatternLiteral::NumPattern { neg: false, num: NatLiteral(1) }),
vec![exst!(s "1")],
Some(vec![exst!(s "2")]),
))
}
)
}
2019-09-11 19:06:00 -07:00
parse_test_wrap_ast! {
"if x is true then 1 else 2",
exst!(
IfExpression {
discriminator: bx!(Discriminator::Simple(Meta::new(ex!(s "x")))),
body: bx!(IfExpressionBody::SimplePatternMatch(
Pattern::Literal(PatternLiteral::BoolPattern(true)),
vec![exst!(NatLiteral(1))],
Some(vec![exst!(NatLiteral(2))]),
))
}
)
}
parse_test_wrap_ast! {
"if x is \"gnosticism\" then 1 else 2",
exst!(
IfExpression {
2019-09-02 14:13:53 -07:00
discriminator: bx!(Discriminator::Simple(Meta::new(ex!(s "x")))),
body: bx!(IfExpressionBody::SimplePatternMatch(
Pattern::Literal(PatternLiteral::StringPattern(rc!(gnosticism))),
vec![exst!(s "1")],
Some(vec![exst!(s "2")]),
))
}
)
}
}