2019-06-16 14:59:11 -07:00
|
|
|
#![cfg(test)]
|
2021-10-19 22:24:27 -07:00
|
|
|
#![allow(clippy::upper_case_acronyms)]
|
2021-10-19 22:29:41 -07:00
|
|
|
#![allow(clippy::vec_init_then_push)]
|
2021-10-19 22:24:27 -07:00
|
|
|
|
2019-10-25 01:49:15 -07:00
|
|
|
use std::rc::Rc;
|
2019-08-14 07:25:45 -07:00
|
|
|
|
2021-10-14 06:18:17 -07:00
|
|
|
use crate::tokenizing::Location;
|
2019-10-25 01:49:15 -07:00
|
|
|
use super::{Parser, ParseResult, tokenize};
|
2019-10-22 03:15:41 -07:00
|
|
|
use crate::ast::*;
|
2019-06-16 14:59:11 -07:00
|
|
|
use super::Declaration::*;
|
|
|
|
use super::Signature;
|
|
|
|
use super::TypeIdentifier::*;
|
|
|
|
use super::TypeSingletonName;
|
|
|
|
use super::ExpressionKind::*;
|
2021-10-21 19:53:50 -07:00
|
|
|
use super::VariantKind::*;
|
2019-06-16 14:59:11 -07:00
|
|
|
|
2019-10-25 01:49:15 -07:00
|
|
|
fn make_parser(input: &str) -> Parser {
|
2019-06-16 14:59:11 -07:00
|
|
|
let tokens: Vec<crate::tokenizing::Token> = tokenize(input);
|
2021-10-14 06:18:17 -07:00
|
|
|
let mut parser = super::Parser::new();
|
2019-10-25 01:49:15 -07:00
|
|
|
parser.add_new_tokens(tokens);
|
|
|
|
parser
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse(input: &str) -> ParseResult<AST> {
|
|
|
|
let mut parser = make_parser(input);
|
2019-06-16 14:59:11 -07:00
|
|
|
parser.parse()
|
|
|
|
}
|
|
|
|
|
2021-10-14 06:18:17 -07:00
|
|
|
//TODO maybe can be const?
|
|
|
|
fn make_statement(kind: StatementKind) -> Statement {
|
|
|
|
Statement {
|
|
|
|
location: Location::default(),
|
|
|
|
id: ItemId::default(),
|
|
|
|
kind,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-14 17:42:04 -07:00
|
|
|
macro_rules! bx {
|
|
|
|
($e:expr) => {
|
|
|
|
Box::new($e)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-06-16 14:59:11 -07:00
|
|
|
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)
|
|
|
|
};
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
macro_rules! parse_test_wrap_ast {
|
2021-10-26 14:05:27 -07:00
|
|
|
($string:expr, $correct:expr) => { parse_test!($string, AST { id: Default::default(), statements: vec![$correct].into() }) }
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
2019-09-19 01:34:21 -07:00
|
|
|
macro_rules! qname {
|
|
|
|
( $( $component:expr),* ) => {
|
|
|
|
{
|
|
|
|
let mut components = vec![];
|
|
|
|
$(
|
|
|
|
components.push(rc!($component));
|
|
|
|
)*
|
2021-10-18 17:39:20 -07:00
|
|
|
QualifiedName { components, id: Default::default() }
|
2019-09-19 01:34:21 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2019-06-16 14:59:11 -07:00
|
|
|
macro_rules! val {
|
2021-10-18 17:39:20 -07:00
|
|
|
($var:expr) => { Value(QualifiedName { components: vec![Rc::new($var.to_string())], id: Default::default() }) };
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
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) => {
|
2021-10-14 06:18:17 -07:00
|
|
|
make_statement(StatementKind::Declaration($expr_type))
|
2019-09-17 02:25:11 -07:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2019-06-16 14:59:11 -07:00
|
|
|
macro_rules! ex {
|
2021-10-18 17:39:20 -07:00
|
|
|
($expr_type:expr) => { Expression::new(Default::default(), $expr_type) };
|
|
|
|
($expr_type:expr, $type_anno:expr) => { Expression::with_anno(Default::default(), $expr_type, $type_anno) };
|
2019-06-16 14:59:11 -07:00
|
|
|
(s $expr_text:expr) => {
|
|
|
|
{
|
2019-10-25 01:49:15 -07:00
|
|
|
let mut parser = make_parser($expr_text);
|
2019-06-16 14:59:11 -07:00
|
|
|
parser.expression().unwrap()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! inv {
|
2019-09-02 14:41:09 -07:00
|
|
|
($expr_type:expr) => { InvocationArgument::Positional($expr_type) }
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! exst {
|
2021-10-18 17:39:20 -07:00
|
|
|
($expr_type:expr) => { make_statement(StatementKind::Expression(Expression::new(Default::default(), $expr_type).into())) };
|
|
|
|
($expr_type:expr, $type_anno:expr) => { make_statement(StatementKind::Expression(Expression::with_anno(Default::default(), $expr_type, $type_anno).into())) };
|
2021-10-14 06:18:17 -07:00
|
|
|
($op:expr, $lhs:expr, $rhs:expr) => { make_statement(StatementKind::Expression(ex!(binexp!($op, $lhs, $rhs)))) };
|
2019-06-16 14:59:11 -07:00
|
|
|
(s $statement_text:expr) => {
|
|
|
|
{
|
2019-10-25 01:49:15 -07:00
|
|
|
let mut parser = make_parser($statement_text);
|
2019-09-20 10:10:57 -07:00
|
|
|
parser.statement().unwrap()
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parsing_types() {
|
2021-10-21 20:00:26 -07:00
|
|
|
parse_test_wrap_ast!("type Yolo = Yolo", decl!(TypeDecl { name: tys!("Yolo"), body: TypeBody(vec![Variant { id: ItemId::default(), kind: UnitStruct, name: rc!(Yolo) }]), mutable: false} ));
|
|
|
|
parse_test_wrap_ast!("type mut Yolo = Yolo", decl!(TypeDecl { name: tys!("Yolo"), body: TypeBody(vec![Variant { id: ItemId::default(), kind: UnitStruct, name: rc!(Yolo) }]), mutable: true} ));
|
2019-09-28 02:42:18 -07:00
|
|
|
parse_test_wrap_ast!("type alias Sex = Drugs", decl!(TypeAlias { alias: rc!(Sex), original: 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-20 10:10:57 -07:00
|
|
|
decl!(TypeDecl {
|
2019-06-16 14:59:11 -07:00
|
|
|
name: tys!("Sanchez"),
|
|
|
|
body: TypeBody(vec![
|
2021-10-21 19:53:50 -07:00
|
|
|
Variant {
|
2021-10-21 20:00:26 -07:00
|
|
|
id: ItemId::default(),
|
|
|
|
kind: UnitStruct, name: rc!(Miguel) },
|
|
|
|
Variant {
|
|
|
|
id: ItemId::default(),
|
2021-10-21 19:53:50 -07:00
|
|
|
name: rc!(Alejandro),
|
|
|
|
kind: TupleStruct(vec![
|
2019-06-16 14:59:11 -07:00
|
|
|
Singleton(TypeSingletonName { name: rc!(Int), params: vec![] }),
|
|
|
|
Singleton(TypeSingletonName { name: rc!(Option), params: vec![Singleton(TypeSingletonName { name: rc!(a), params: vec![] })] }),
|
2021-10-21 19:53:50 -07:00
|
|
|
])
|
|
|
|
},
|
|
|
|
Variant {
|
2021-10-21 20:00:26 -07:00
|
|
|
id: ItemId::default(),
|
2021-10-21 19:53:50 -07:00
|
|
|
name: rc!(Esperanza),
|
|
|
|
kind: Record(vec![
|
2019-06-16 14:59:11 -07:00
|
|
|
(rc!(a), Singleton(TypeSingletonName { name: rc!(Int), params: vec![] })),
|
|
|
|
(rc!(b), Singleton(TypeSingletonName { name: rc!(String), params: vec![] })),
|
2021-10-21 19:53:50 -07:00
|
|
|
])
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
]),
|
|
|
|
mutable: false
|
2019-09-20 10:10:57 -07:00
|
|
|
}));
|
2019-06-16 14:59:11 -07:00
|
|
|
|
2019-09-11 19:06:00 -07:00
|
|
|
parse_test_wrap_ast! {
|
|
|
|
"type Jorge<a> = Diego | Kike(a)",
|
2019-09-20 10:10:57 -07:00
|
|
|
decl!(TypeDecl{
|
2019-06-16 14:59:11 -07:00
|
|
|
name: TypeSingletonName { name: rc!(Jorge), params: vec![Singleton(TypeSingletonName { name: rc!(a), params: vec![] })] },
|
2021-10-21 20:00:26 -07:00
|
|
|
body: TypeBody(vec![Variant{ id: ItemId::default(), kind: UnitStruct, name: rc!(Diego) }, Variant { id: ItemId::default(), name: rc!(Kike), kind: TupleStruct( vec![Singleton(TypeSingletonName { name: rc!(a), params: vec![] })]) }]),
|
2019-06-16 14:59:11 -07:00
|
|
|
mutable: false
|
|
|
|
}
|
2019-09-20 10:10:57 -07:00
|
|
|
)
|
2019-09-11 19:06:00 -07:00
|
|
|
};
|
2019-06-16 14:59:11 -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!(
|
2019-06-16 14:59:11 -07:00
|
|
|
IfExpression {
|
2019-10-10 18:17:59 -07:00
|
|
|
discriminator: Some(bx! {
|
|
|
|
ex!(Call { f: bx!(ex!(val!("a"))), arguments: vec![]})
|
|
|
|
}),
|
2019-06-16 14:59:11 -07:00
|
|
|
body: bx! {
|
2019-10-10 18:17:59 -07:00
|
|
|
IfExpressionBody::SimpleConditional {
|
2021-10-26 14:05:27 -07:00
|
|
|
then_case: vec![exst!(Call { f: bx!(ex!(val!("b"))), arguments: vec![]}), exst!(Call { f: bx!(ex!(val!("c"))), arguments: vec![] })].into(),
|
2019-10-10 18:17:59 -07:00
|
|
|
else_case: None,
|
|
|
|
}
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
}
|
2019-09-11 19:06:00 -07:00
|
|
|
)
|
2019-06-16 14:59:11 -07:00
|
|
|
};
|
|
|
|
|
2019-09-11 19:06:00 -07:00
|
|
|
parse_test_wrap_ast! {
|
|
|
|
"if a() then { b(); c() } else { q }", exst!(
|
2019-06-16 14:59:11 -07:00
|
|
|
IfExpression {
|
2019-10-10 18:17:59 -07:00
|
|
|
discriminator: Some(bx! {
|
|
|
|
ex!(Call { f: bx!(ex!(val!("a"))), arguments: vec![]})
|
|
|
|
}),
|
2019-06-16 14:59:11 -07:00
|
|
|
body: bx! {
|
2019-10-10 18:17:59 -07:00
|
|
|
IfExpressionBody::SimpleConditional {
|
2021-10-26 14:05:27 -07:00
|
|
|
then_case: vec![exst!(Call { f: bx!(ex!(val!("b"))), arguments: vec![]}), exst!(Call { f: bx!(ex!(val!("c"))), arguments: vec![] })].into(),
|
|
|
|
else_case: Some(vec![exst!(val!("q"))].into()),
|
2019-10-10 18:17:59 -07:00
|
|
|
}
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
}
|
2019-09-11 19:06:00 -07:00
|
|
|
)
|
2019-06-16 14:59:11 -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)) }),
|
2019-06-16 14:59:11 -07:00
|
|
|
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_impls() {
|
2019-09-11 19:06:00 -07:00
|
|
|
parse_test_wrap_ast!("impl Heh { fn yolo(); fn swagg(); }",
|
2019-09-20 10:10:57 -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-06-16 14:59:11 -07:00
|
|
|
|
2019-09-11 19:06:00 -07:00
|
|
|
parse_test_wrap_ast!("impl Mondai for Lollerino { fn yolo(); fn swagg(); }",
|
2019-09-20 10:10:57 -07:00
|
|
|
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-06-16 14:59:11 -07:00
|
|
|
|
2019-09-11 19:06:00 -07:00
|
|
|
parse_test_wrap_ast!("impl Hella<T> for (Alpha, Omega) { }",
|
2019-09-20 10:10:57 -07:00
|
|
|
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-06-16 14:59:11 -07:00
|
|
|
|
2019-09-11 19:06:00 -07:00
|
|
|
parse_test_wrap_ast!("impl Option<WTFMate> { fn oi() }",
|
2019-09-20 10:10:57 -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-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn parsing_lambdas() {
|
|
|
|
parse_test_wrap_ast! { r#"\(x) { x + 1}"#, exst!(
|
2021-10-26 14:05:27 -07:00
|
|
|
Lambda { params: vec![FormalParam { name: rc!(x), anno: None, default: None } ], type_anno: None, body: exst!(s "x + 1").into() }
|
2019-06-16 14:59:11 -07:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-09-11 19:06:00 -07:00
|
|
|
parse_test_wrap_ast!(r#"\ (x: Int, y) { a;b;c;}"#,
|
2019-06-16 14:59:11 -07:00
|
|
|
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,
|
2021-10-26 14:05:27 -07:00
|
|
|
body: vec![exst!(s "a"), exst!(s "b"), exst!(s "c")].into()
|
2019-06-16 14:59:11 -07:00
|
|
|
})
|
2019-09-11 19:06:00 -07:00
|
|
|
);
|
2019-06-16 14:59:11 -07:00
|
|
|
|
2019-09-11 19:06:00 -07:00
|
|
|
parse_test_wrap_ast! { r#"\(x){y}(1)"#,
|
2019-09-20 10:10:57 -07:00
|
|
|
exst!(Call { f: bx!(ex!(
|
2019-06-16 14:59:11 -07:00
|
|
|
Lambda {
|
|
|
|
params: vec![
|
|
|
|
FormalParam { name: rc!(x), anno: None, default: None }
|
|
|
|
],
|
|
|
|
type_anno: None,
|
2021-10-26 14:05:27 -07:00
|
|
|
body: exst!(s "y").into() }
|
2019-06-16 14:59:11 -07:00
|
|
|
)),
|
2021-10-19 21:53:30 -07:00
|
|
|
arguments: vec![inv!(ex!(NatLiteral(1)))] })
|
2019-09-11 19:06:00 -07:00
|
|
|
};
|
2019-06-16 14:59:11 -07:00
|
|
|
|
|
|
|
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")),
|
2021-10-26 14:05:27 -07:00
|
|
|
body: exst!(s r#""q""#).into()
|
2019-06-16 14:59:11 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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,
|
2021-10-26 14:05:27 -07:00
|
|
|
body: exst!(s r"x + 10").into()
|
2019-06-16 14:59:11 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2021-10-26 14:05:27 -07:00
|
|
|
body: exst!(s r"x + 10").into()
|
2019-06-16 14:59:11 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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 {
|
2021-10-18 17:39:20 -07:00
|
|
|
id: Default::default(),
|
2019-09-11 19:06:00 -07:00
|
|
|
statements: vec![
|
|
|
|
exst!(s r"fn wahoo() { let a = 10; \(x) { x + a } }"),
|
|
|
|
exst! {
|
2019-06-16 14:59:11 -07:00
|
|
|
Call {
|
2019-09-20 10:10:57 -07:00
|
|
|
f: bx!(ex!(Call { f: bx!(ex!(val!("wahoo"))), arguments: vec![] })),
|
2021-10-19 21:53:30 -07:00
|
|
|
arguments: vec![inv!(ex!(NatLiteral(3)))],
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
}
|
2021-10-26 14:05:27 -07:00
|
|
|
].into()
|
2019-09-11 19:06:00 -07:00
|
|
|
}
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn list_literals() {
|
2019-09-11 19:06:00 -07:00
|
|
|
parse_test_wrap_ast! {
|
|
|
|
"[1,2]",
|
2019-09-20 10:10:57 -07:00
|
|
|
exst!(ListLiteral(vec![ex!(NatLiteral(1)), ex!(NatLiteral(2))]))
|
2019-06-16 14:59:11 -07:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn patterns() {
|
|
|
|
parse_test_wrap_ast! {
|
|
|
|
"if x is Some(a) then { 4 } else { 9 }", exst!(
|
|
|
|
IfExpression {
|
2019-10-10 18:17:59 -07:00
|
|
|
discriminator: Some(bx!(ex!(s "x"))),
|
|
|
|
body: bx!(IfExpressionBody::SimplePatternMatch {
|
|
|
|
pattern: Pattern::TupleStruct(qname!(Some), vec![Pattern::VarOrName(qname!(a))]),
|
2021-10-26 14:05:27 -07:00
|
|
|
then_case: vec![exst!(s "4")].into(),
|
|
|
|
else_case: Some(vec![exst!(s "9")].into()) })
|
2019-10-10 18:17:59 -07:00
|
|
|
}
|
2019-06-16 14:59:11 -07:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
parse_test_wrap_ast! {
|
|
|
|
"if x is Some(a) then 4 else 9", exst!(
|
|
|
|
IfExpression {
|
2019-10-10 18:17:59 -07:00
|
|
|
discriminator: Some(bx!(ex!(s "x"))),
|
|
|
|
body: bx!(IfExpressionBody::SimplePatternMatch {
|
|
|
|
pattern: Pattern::TupleStruct(qname!(Some), vec![Pattern::VarOrName(qname!(a))]),
|
2021-10-26 14:05:27 -07:00
|
|
|
then_case: vec![exst!(s "4")].into(),
|
|
|
|
else_case: Some(vec![exst!(s "9")].into()) }
|
2019-10-10 18:17:59 -07:00
|
|
|
)
|
|
|
|
}
|
2019-06-16 14:59:11 -07:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
parse_test_wrap_ast! {
|
|
|
|
"if x is Something { a, b: x } then { 4 } else { 9 }", exst!(
|
|
|
|
IfExpression {
|
2019-10-10 18:17:59 -07:00
|
|
|
discriminator: Some(bx!(ex!(s "x"))),
|
|
|
|
body: bx!(IfExpressionBody::SimplePatternMatch {
|
|
|
|
pattern: Pattern::Record(qname!(Something), vec![
|
|
|
|
(rc!(a),Pattern::Literal(PatternLiteral::StringPattern(rc!(a)))),
|
|
|
|
(rc!(b),Pattern::VarOrName(qname!(x)))
|
2019-06-16 14:59:11 -07:00
|
|
|
]),
|
2021-10-26 14:05:27 -07:00
|
|
|
then_case: vec![exst!(s "4")].into(),
|
|
|
|
else_case: Some(vec![exst!(s "9")].into())
|
2019-10-10 18:17:59 -07:00
|
|
|
}
|
|
|
|
)
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn pattern_literals() {
|
|
|
|
parse_test_wrap_ast! {
|
|
|
|
"if x is -1 then 1 else 2",
|
|
|
|
exst!(
|
|
|
|
IfExpression {
|
2019-10-10 18:17:59 -07:00
|
|
|
discriminator: Some(bx!(ex!(s "x"))),
|
|
|
|
body: bx!(IfExpressionBody::SimplePatternMatch {
|
|
|
|
pattern: Pattern::Literal(PatternLiteral::NumPattern { neg: true, num: NatLiteral(1) }),
|
2021-10-26 14:05:27 -07:00
|
|
|
then_case: vec![exst!(NatLiteral(1))].into(),
|
|
|
|
else_case: Some(vec![exst!(NatLiteral(2))].into()),
|
2019-10-10 18:17:59 -07:00
|
|
|
})
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
parse_test_wrap_ast! {
|
2019-09-20 10:10:57 -07:00
|
|
|
"if x is 1 then 1 else 2",
|
2019-06-16 14:59:11 -07:00
|
|
|
exst!(
|
|
|
|
IfExpression {
|
2019-10-10 18:17:59 -07:00
|
|
|
discriminator: Some(bx!(ex!(s "x"))),
|
|
|
|
body: bx!(IfExpressionBody::SimplePatternMatch {
|
|
|
|
pattern: Pattern::Literal(PatternLiteral::NumPattern { neg: false, num: NatLiteral(1) }),
|
2021-10-26 14:05:27 -07:00
|
|
|
then_case: vec![exst!(s "1")].into(),
|
|
|
|
else_case: Some(vec![exst!(s "2")].into()),
|
2019-10-10 18:17:59 -07:00
|
|
|
})
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-09-11 19:06:00 -07:00
|
|
|
parse_test_wrap_ast! {
|
2019-09-20 10:10:57 -07:00
|
|
|
"if x is true then 1 else 2",
|
2019-09-11 19:06:00 -07:00
|
|
|
exst!(
|
|
|
|
IfExpression {
|
2019-10-10 18:17:59 -07:00
|
|
|
discriminator: Some(bx!(ex!(s "x"))),
|
|
|
|
body: bx!(
|
|
|
|
IfExpressionBody::SimplePatternMatch {
|
|
|
|
pattern: Pattern::Literal(PatternLiteral::BoolPattern(true)),
|
2021-10-26 14:05:27 -07:00
|
|
|
then_case: vec![exst!(NatLiteral(1))].into(),
|
|
|
|
else_case: Some(vec![exst!(NatLiteral(2))].into()),
|
2019-10-10 18:17:59 -07:00
|
|
|
})
|
2019-09-11 19:06:00 -07:00
|
|
|
}
|
|
|
|
)
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
parse_test_wrap_ast! {
|
|
|
|
"if x is \"gnosticism\" then 1 else 2",
|
|
|
|
exst!(
|
|
|
|
IfExpression {
|
2019-10-10 18:17:59 -07:00
|
|
|
discriminator: Some(bx!(ex!(s "x"))),
|
|
|
|
body: bx!(IfExpressionBody::SimplePatternMatch {
|
|
|
|
pattern: Pattern::Literal(PatternLiteral::StringPattern(rc!(gnosticism))),
|
2021-10-26 14:05:27 -07:00
|
|
|
then_case: vec![exst!(s "1")].into(),
|
|
|
|
else_case: Some(vec![exst!(s "2")].into()),
|
2019-10-10 18:17:59 -07:00
|
|
|
})
|
2019-06-16 14:59:11 -07:00
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2019-09-21 02:30:28 -07:00
|
|
|
|
2019-10-09 01:50:32 -07:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn if_expr() {
|
|
|
|
parse_test_wrap_ast! {
|
2019-10-11 09:13:09 -07:00
|
|
|
"if x { is 1 then 5, else 20 }",
|
2019-10-09 01:50:32 -07:00
|
|
|
exst! {
|
|
|
|
IfExpression {
|
2019-10-10 18:17:59 -07:00
|
|
|
discriminator: Some(bx!(ex!(s "x"))),
|
|
|
|
body: bx!(IfExpressionBody::CondList(
|
2019-10-09 01:50:32 -07:00
|
|
|
vec![
|
2019-10-10 18:17:59 -07:00
|
|
|
ConditionArm {
|
|
|
|
condition: Condition::Pattern(Pattern::Literal(PatternLiteral::NumPattern { neg: false, num: NatLiteral(1)})),
|
|
|
|
guard: None,
|
2021-10-26 14:05:27 -07:00
|
|
|
body: vec![exst!(s "5")].into(),
|
2019-10-09 01:50:32 -07:00
|
|
|
},
|
2019-10-10 18:17:59 -07:00
|
|
|
ConditionArm {
|
|
|
|
condition: Condition::Else,
|
|
|
|
guard: None,
|
2021-10-26 14:05:27 -07:00
|
|
|
body: vec![exst!(s "20")].into(),
|
2019-10-09 01:50:32 -07:00
|
|
|
},
|
|
|
|
]
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-10-22 03:15:14 -07:00
|
|
|
|
2021-10-26 00:39:24 -07:00
|
|
|
#[test]
|
|
|
|
fn advanced_if_expr() {
|
|
|
|
|
|
|
|
parse_test_wrap_ast! {
|
|
|
|
r#"
|
|
|
|
if (45, "panda", false, 2.2) {
|
|
|
|
is (49, "pablo", _, 28.4) then "no"
|
|
|
|
is (_, "panda", _, -2.2) then "yes"
|
|
|
|
is _ then "maybe"
|
|
|
|
}"#,
|
|
|
|
exst!(
|
|
|
|
IfExpression {
|
|
|
|
discriminator: Some(bx!(ex!(s r#"(45, "panda", false, 2.2)"#))),
|
|
|
|
body: bx!(IfExpressionBody::CondList(vec![
|
|
|
|
ConditionArm {
|
|
|
|
condition: Condition::Pattern(Pattern::TuplePattern(
|
|
|
|
vec![
|
|
|
|
Pattern::Literal(PatternLiteral::NumPattern { neg: false, num: NatLiteral(49) }),
|
|
|
|
Pattern::Literal(PatternLiteral::StringPattern(rc!(pablo))),
|
|
|
|
Pattern::Ignored,
|
|
|
|
Pattern::Literal(PatternLiteral::NumPattern { neg: false, num: FloatLiteral(28.4) }),
|
|
|
|
]
|
|
|
|
)),
|
|
|
|
guard: None,
|
2021-10-26 14:05:27 -07:00
|
|
|
body: vec![exst!(s r#""no""#)].into(),
|
2021-10-26 00:39:24 -07:00
|
|
|
},
|
|
|
|
ConditionArm {
|
|
|
|
condition: Condition::Pattern(Pattern::TuplePattern(
|
|
|
|
vec![
|
|
|
|
Pattern::Ignored,
|
|
|
|
Pattern::Literal(PatternLiteral::StringPattern(rc!(panda))),
|
|
|
|
Pattern::Ignored,
|
|
|
|
Pattern::Literal(PatternLiteral::NumPattern { neg: true, num: FloatLiteral(2.2) }),
|
|
|
|
]
|
|
|
|
)),
|
|
|
|
guard: None,
|
2021-10-26 14:05:27 -07:00
|
|
|
body: vec![exst!(s r#""yes""#)].into(),
|
2021-10-26 00:39:24 -07:00
|
|
|
},
|
|
|
|
ConditionArm {
|
|
|
|
condition: Condition::Pattern(Pattern::Ignored),
|
|
|
|
guard: None,
|
2021-10-26 14:05:27 -07:00
|
|
|
body: vec![exst!(s r#""maybe""#)].into(),
|
2021-10-26 00:39:24 -07:00
|
|
|
},
|
|
|
|
]))
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|