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

1462 lines
45 KiB
Rust
Raw Normal View History

#![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-31 02:05:39 -07:00
//use test_case::test_case;
use std::{fmt::Write, rc::Rc};
2021-10-19 22:24:27 -07:00
2021-10-30 20:27:16 -07:00
use pretty_assertions::assert_eq;
use super::Parser;
use crate::{ast::*, parsing::Location};
2021-10-31 02:05:39 -07:00
fn rc(s: &str) -> Rc<String> {
Rc::new(s.to_owned())
}
fn bx<T>(item: T) -> Box<T> {
Box::new(item)
}
2021-11-21 01:02:59 -08:00
fn strlit(s: &str) -> ExpressionKind {
ExpressionKind::StringLiteral { s: Rc::new(s.to_string()), prefix: None }
}
2021-10-31 02:05:39 -07:00
fn stmt(kind: StatementKind) -> Statement {
Statement { location: Location::default(), id: ItemId::default(), kind }
}
2021-10-31 02:05:39 -07:00
fn exst(kind: ExpressionKind) -> Statement {
Statement {
location: Location::default(),
id: ItemId::default(),
kind: StatementKind::Expression(expr(kind)),
}
2021-10-14 17:42:04 -07:00
}
2021-10-31 02:05:39 -07:00
fn decl(declaration: Declaration) -> Statement {
Statement {
location: Location::default(),
id: ItemId::default(),
kind: StatementKind::Declaration(declaration),
}
}
2021-10-31 02:05:39 -07:00
fn fn_decl(sig: Signature, stmts: Block) -> Statement {
Statement {
kind: StatementKind::Declaration(Declaration::FuncDecl(sig, stmts)),
location: Default::default(),
id: Default::default(),
}
}
2021-10-31 02:05:39 -07:00
fn expr_anno(kind: ExpressionKind, anno: TypeIdentifier) -> Expression {
Expression { id: ItemId::default(), kind, type_anno: Some(anno) }
}
fn expr(kind: ExpressionKind) -> Expression {
Expression { id: ItemId::default(), kind, type_anno: None }
}
fn binop(sigil: &str, lhs: Expression, rhs: Expression) -> Expression {
Expression {
id: Default::default(),
type_anno: None,
kind: ExpressionKind::BinExp(BinOp::from_sigil(sigil), Box::new(lhs), Box::new(rhs)),
}
}
fn prefixop(sigil: &str, exp: Expression) -> Expression {
Expression {
id: Default::default(),
type_anno: None,
kind: ExpressionKind::PrefixExp(PrefixOp::from_sigil(sigil), Box::new(exp)),
}
}
macro_rules! qn {
( $( $component:ident),* ) => {
2019-09-19 01:34:21 -07:00
{
2021-10-31 02:05:39 -07:00
let mut components = vec![];
$(
components.push(rc(stringify!($component)));
)*
QualifiedName { components, id: Default::default() }
2019-09-19 01:34:21 -07:00
}
};
}
2021-10-31 02:05:39 -07:00
fn ty_simple(name: &str) -> TypeIdentifier {
TypeIdentifier::Singleton(TypeSingletonName { name: rc(name), params: vec![] })
}
2021-10-31 02:05:39 -07:00
2021-11-19 09:59:08 -08:00
macro_rules! assert_ast {
2021-11-18 15:17:47 -08:00
($input:expr, $statements:expr) => {
let mut parser = Parser::new();
let ast = parser.parse_comb($input);
2021-11-20 11:04:56 -08:00
let ast2 = parser.parse_peg($input);
2021-11-18 15:17:47 -08:00
let expected = AST { id: Default::default(), statements: $statements.into() };
2021-11-20 11:04:56 -08:00
let ast = match ast {
Err(err) => {
println!("Parse error: {}", err.msg);
panic!();
2021-11-20 22:55:11 -08:00
}
2021-11-20 11:04:56 -08:00
Ok(ast) => ast,
};
assert_eq!(ast, ast2.unwrap());
assert_eq!(ast, expected);
2021-11-07 03:13:35 -08:00
};
}
2021-11-19 23:04:00 -08:00
macro_rules! assert_fail {
($input:expr) => {
let mut parser = Parser::new();
2021-11-20 22:55:11 -08:00
let _err = parser.parse_comb($input).unwrap_err();
2021-11-19 23:04:00 -08:00
};
2021-11-19 09:59:08 -08:00
($input:expr, $failure:expr) => {
let mut parser = Parser::new();
let err = parser.parse_comb($input).unwrap_err();
2021-11-19 20:43:37 -08:00
println!("assert_fail: {}", err.msg);
2021-11-19 09:59:08 -08:00
assert_eq!(err.msg, $failure);
};
}
2021-11-19 01:35:25 -08:00
macro_rules! assert_expr {
2021-11-17 16:53:03 -08:00
($input:expr, $correct:expr) => {
let mut parser = Parser::new();
2021-11-19 00:40:10 -08:00
let expr = parser.expression_comb($input.trim_start());
2021-11-20 11:04:56 -08:00
let expr2 = parser.expression($input.trim_start());
let expr = match expr {
Err(err) => {
println!("Expression parse error: {}", err.msg);
panic!();
2021-11-20 22:55:11 -08:00
}
2021-11-20 11:04:56 -08:00
Ok(expr) => expr,
};
assert_eq!(expr, expr2.unwrap());
assert_eq!(expr, $correct);
2021-11-04 21:11:19 -07:00
};
2021-11-03 20:31:46 -07:00
}
2021-11-20 00:03:05 -08:00
macro_rules! assert_fail_expr {
($input:expr, $failure:expr) => {
let mut parser = Parser::new();
let _err = parser.expression_comb($input).unwrap_err();
//TODO make real tests for failures
//assert_eq!(err.to_string(), $failure);
};
}
2021-11-20 23:00:19 -08:00
macro_rules! assert_block {
($input:expr, $correct:expr) => {
let mut parser = Parser::new();
let block = parser.block_comb($input);
let block2 = parser.block($input);
let block = match block {
Err(err) => {
println!("Expression parse error: {}", err.msg);
panic!();
}
Ok(item) => item,
};
assert_eq!(block, block2.unwrap());
assert_eq!(block, $correct);
};
}
2021-10-31 02:05:39 -07:00
#[test]
fn basic_literals() {
use ExpressionKind::*;
2021-11-19 01:35:25 -08:00
assert_expr!(".2", expr(FloatLiteral(0.2)));
assert_expr!("8.1", expr(FloatLiteral(8.1)));
assert_expr!("0b010", expr(NatLiteral(2)));
assert_expr!("0b0_1_0", expr(NatLiteral(2)));
assert_expr!("0xff", expr(NatLiteral(255)));
assert_expr!("0x032f", expr(NatLiteral(815)));
2021-11-20 02:33:09 -08:00
assert_expr!("0xf_f", expr(NatLiteral(255)));
2021-11-19 01:35:25 -08:00
assert_expr!("false", expr(BoolLiteral(false)));
assert_expr!("true", expr(BoolLiteral(true)));
2021-11-13 13:45:52 -08:00
}
#[test]
fn string_literals() {
use ExpressionKind::*;
2021-11-21 01:02:59 -08:00
assert_expr!(r#""""#, expr(strlit("")));
assert_expr!(r#""hello""#, expr(strlit("hello")));
assert_expr!(
r#"b"some bytestring""#,
expr(StringLiteral { s: rc("some bytestring"), prefix: Some(rc("b")) })
);
2021-11-21 01:54:34 -08:00
assert_expr!(r#""Do \n \" escapes work\t""#, expr(strlit("Do \n \" escapes work\t")));
2021-11-21 02:11:20 -08:00
assert_expr!(r#""Georgian letter jani \u{10ef}""#, expr(strlit("Georgian letter jani ჯ")));
2021-10-31 02:05:39 -07:00
}
#[test]
fn list_literals() {
use ExpressionKind::*;
2021-11-19 01:35:25 -08:00
assert_expr!("[]", expr(ListLiteral(vec![])));
assert_expr!("[1,2]", expr(ListLiteral(vec![expr(NatLiteral(1)), expr(NatLiteral(2)),])));
assert_expr!("[1, /*no*/2]", expr(ListLiteral(vec![expr(NatLiteral(1)), expr(NatLiteral(2)),])));
2021-11-13 01:42:49 -08:00
assert_fail_expr!("[1,,2]", "some failure");
2021-10-31 02:05:39 -07:00
}
#[test]
fn binexps() {
use ExpressionKind::*;
use StatementKind::Expression;
2021-11-19 01:35:25 -08:00
assert_expr!("0xf_f+1", binop("+", expr(NatLiteral(255)), expr(NatLiteral(1))));
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-11-04 21:11:19 -07:00
"3; 4; 4.3",
vec![
stmt(Expression(expr(NatLiteral(3)))),
stmt(Expression(expr(NatLiteral(4)))),
stmt(Expression(expr(FloatLiteral(4.3)))),
]
2021-10-31 02:05:39 -07:00
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"1 + 2 * 3",
binop("+", expr(NatLiteral(1)), binop("*", expr(NatLiteral(2)), expr(NatLiteral(3))))
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"1 * 2 + 3",
binop("+", binop("*", expr(NatLiteral(1)), expr(NatLiteral(2))), expr(NatLiteral(3)))
);
2021-11-19 01:35:25 -08:00
assert_expr!("1 && 2", binop("&&", expr(NatLiteral(1)), expr(NatLiteral(2))));
assert_expr!(
2021-10-31 02:05:39 -07:00
"1 + 2 * 3 + 4",
binop(
"+",
binop("+", expr(NatLiteral(1)), binop("*", expr(NatLiteral(2)), expr(NatLiteral(3)))),
expr(NatLiteral(4))
)
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"(1 + 2) * 3",
binop("*", binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))), expr(NatLiteral(3)))
);
2021-11-19 01:35:25 -08:00
assert_expr!(".1 + .2", binop("+", expr(FloatLiteral(0.1)), expr(FloatLiteral(0.2))));
assert_expr!("1 / 2.", binop("/", expr(NatLiteral(1)), expr(FloatLiteral(2.))));
2021-10-31 02:05:39 -07:00
}
#[test]
fn prefix_exps() {
use ExpressionKind::*;
2021-11-19 01:35:25 -08:00
assert_expr!("-3", prefixop("-", expr(NatLiteral(3))));
assert_expr!("-0.2", prefixop("-", expr(FloatLiteral(0.2))));
assert_expr!("!3", prefixop("!", expr(NatLiteral(3))));
assert_expr!("!t", prefixop("!", expr(Value(qn!(t)))));
assert_expr!("a <- -b", binop("<-", expr(Value(qn!(a))), prefixop("-", expr(Value(qn!(b))))));
assert_expr!("a <--b", binop("<--", expr(Value(qn!(a))), expr(Value(qn!(b)))));
2021-10-31 02:05:39 -07:00
}
#[test]
fn operators() {
use ExpressionKind::*;
2021-11-19 01:35:25 -08:00
assert_expr!("a <- 1", binop("<-", expr(Value(qn!(a))), expr(NatLiteral(1))));
assert_expr!("a || 1", binop("||", expr(Value(qn!(a))), expr(NatLiteral(1))));
assert_expr!("a <> 1", binop("<>", expr(Value(qn!(a))), expr(NatLiteral(1))));
2021-10-31 02:05:39 -07:00
}
#[test]
fn accessors() {
use ExpressionKind::*;
2021-11-19 01:35:25 -08:00
assert_expr!("a.b", expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }));
assert_expr!(
2021-10-31 02:05:39 -07:00
"a.b.c",
expr(Access {
name: rc("c"),
expr: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }))
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"a.b.c(3)",
expr(Call {
f: bx(expr(Access {
name: rc("c"),
expr: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }))
})),
arguments: vec![InvocationArgument::Positional(expr(NatLiteral(3)))],
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"a.b().c",
expr(Access {
name: rc("c"),
expr: bx(expr(Call {
f: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) })),
arguments: vec![]
}))
})
);
}
#[test]
fn tuples() {
use ExpressionKind::*;
2021-11-19 01:35:25 -08:00
assert_expr!("()", expr(TupleLiteral(vec![])));
2021-11-21 01:02:59 -08:00
assert_expr!(r#"("hella", 34)"#, expr(TupleLiteral(vec![expr(strlit("hella")), expr(NatLiteral(34))])));
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
r#"(1+2, "slough")"#,
expr(TupleLiteral(vec![
binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))),
2021-11-21 01:02:59 -08:00
expr(strlit("slough")),
2021-10-31 02:05:39 -07:00
]))
);
}
#[test]
fn identifiers() {
use ExpressionKind::*;
2021-11-19 01:35:25 -08:00
assert_expr!("a", expr(Value(qn!(a))));
assert_expr!("some_value", expr(Value(qn!(some_value))));
assert_expr!("alpha::beta::gamma", expr(Value(qn!(alpha, beta, gamma))));
assert_expr!("a + b", binop("+", expr(Value(qn!(a))), expr(Value(qn!(b)))));
assert_expr!("None", expr(Value(qn!(None))));
assert_expr!(
2021-10-31 02:05:39 -07:00
"thing::item::call()",
expr(Call { f: bx(expr(Value(qn!(thing, item, call)))), arguments: vec![] })
);
}
#[test]
fn named_struct() {
use ExpressionKind::*;
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"Pandas { a: x + y }",
expr(NamedStruct {
name: qn!(Pandas),
fields: vec![(rc("a"), binop("+", expr(Value(qn!(x))), expr(Value(qn!(y)))))]
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"Trousers { a:1, b:800 }",
expr(NamedStruct {
name: qn!(Trousers),
fields: vec![(rc("a"), expr(NatLiteral(1))), (rc("b"), expr(NatLiteral(800)))]
})
);
}
#[test]
fn index() {
use ExpressionKind::*;
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-11-04 22:31:29 -07:00
"armok[b,c]",
2021-10-31 02:05:39 -07:00
expr(Index {
2021-11-04 22:31:29 -07:00
indexee: bx(expr(Value(qn!(armok)))),
2021-10-31 02:05:39 -07:00
indexers: vec![expr(Value(qn!(b))), expr(Value(qn!(c)))]
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-11-04 22:31:29 -07:00
"a[b,c][1]",
expr(Index {
indexee: bx(expr(Index {
indexee: bx(expr(Value(qn!(a)))),
indexers: vec![expr(Value(qn!(b))), expr(Value(qn!(c)))]
})),
indexers: vec![expr(NatLiteral(1))]
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"perspicacity()[a]",
expr(Index {
indexee: bx(expr(Call { f: bx(expr(Value(qn!(perspicacity)))), arguments: vec![] })),
indexers: vec![expr(Value(qn!(a)))]
})
);
let a = expr(Call { f: bx(expr(Value(qn!(a)))), arguments: vec![] });
let b = expr(Index { indexee: bx(a), indexers: vec![expr(Value(qn!(b)))] });
let c = expr(Call { f: bx(b), arguments: vec![] });
let d = expr(Index { indexee: bx(c), indexers: vec![expr(Value(qn!(d)))] });
2021-11-19 01:35:25 -08:00
assert_expr!("a()[b]()[d]", d);
2021-10-31 02:05:39 -07:00
2021-11-13 01:42:49 -08:00
assert_fail_expr!("a[]", "Empty index expressions are not allowed");
2021-10-31 02:05:39 -07:00
}
#[test]
fn while_expression() {
use ExpressionKind::*;
2021-11-18 21:02:33 -08:00
// assert_expr_comb!("while { }", expr(WhileExpression { condition: None, body: Block::default() }));
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"while a == b { }",
expr(WhileExpression {
condition: Some(bx(binop("==", expr(Value(qn!(a))), expr(Value(qn!(b)))))),
body: Block::default()
})
);
}
#[test]
fn for_expression() {
use ExpressionKind::*;
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"for { a <- garodzny::maybeValue } return 1",
expr(ForExpression {
2021-11-22 01:59:05 -08:00
enumerators: vec![Enumerator {
identifier: rc("a"),
assignment: false,
generator: expr(Value(qn!(garodzny, maybeValue)))
}],
2021-10-31 02:05:39 -07:00
body: bx(ForBody::MonadicReturn(expr(NatLiteral(1))))
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-11-06 20:33:33 -07:00
"for n <- someRange { f(n) ; }",
2021-10-31 02:05:39 -07:00
expr(ForExpression {
2021-11-22 01:59:05 -08:00
enumerators: vec![Enumerator {
identifier: rc("n"),
assignment: false,
generator: expr(Value(qn!(someRange)))
}],
2021-10-31 02:05:39 -07:00
body: bx(ForBody::StatementBlock(
vec![stmt(StatementKind::Expression(expr(Call {
f: bx(expr(Value(qn!(f)))),
arguments: vec![InvocationArgument::Positional(expr(Value(qn!(n))))],
}))),]
.into()
)),
})
);
}
#[test]
fn lambda_expressions() {
use ExpressionKind::*;
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
r#"\(x) { x + 1}"#,
expr(Lambda {
params: vec![FormalParam { name: rc!(x), anno: None, default: None }],
type_anno: None,
body:
vec![stmt(StatementKind::Expression(binop("+", expr(Value(qn!(x))), expr(NatLiteral(1))))),]
.into()
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
r#"\ (x: Int, y) { a;b;c;}"#,
expr(Lambda {
params: vec![
FormalParam { name: rc!(x), anno: Some(ty_simple("Int")), default: None },
FormalParam { name: rc!(y), anno: None, default: None },
],
type_anno: None,
body: vec![
stmt(StatementKind::Expression(expr(Value(qn!(a))))),
stmt(StatementKind::Expression(expr(Value(qn!(b))))),
stmt(StatementKind::Expression(expr(Value(qn!(c))))),
]
.into()
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
r#"\(x){y}(1)"#,
expr(Call {
f: bx(expr(Lambda {
params: vec![FormalParam { name: rc!(x), anno: None, default: None },],
type_anno: None,
body: vec![stmt(StatementKind::Expression(expr(Value(qn!(y))))),].into()
})),
arguments: vec![InvocationArgument::Positional(expr(NatLiteral(1)))],
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
r#"\(x: Int): String { "q" }"#,
expr(Lambda {
params: vec![FormalParam { name: rc!(x), anno: Some(ty_simple("Int")), default: None },],
type_anno: Some(TypeIdentifier::Singleton(TypeSingletonName {
name: rc("String"),
params: vec![]
})),
2021-11-21 01:02:59 -08:00
body: vec![stmt(StatementKind::Expression(expr(strlit("q")))),].into()
2021-10-31 02:05:39 -07:00
})
);
}
#[test]
fn single_param_lambda() {
use ExpressionKind::*;
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
r#"\x { x + 10 }"#,
expr(Lambda {
params: vec![FormalParam { name: rc!(x), anno: None, default: None },],
type_anno: None,
body: vec![stmt(StatementKind::Expression(binop(
"+",
expr(Value(qn!(x))),
expr(NatLiteral(10))
)))]
.into()
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
r#"\x: Int { x + 10 }"#,
expr(Lambda {
params: vec![FormalParam { name: rc!(x), anno: Some(ty_simple("Int")), default: None },],
type_anno: None,
body: vec![stmt(StatementKind::Expression(binop(
"+",
expr(Value(qn!(x))),
expr(NatLiteral(10))
)))]
.into()
})
);
}
#[test]
fn complex_lambdas() {
use ExpressionKind::*;
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-11-21 02:23:50 -08:00
r#"fn wahoo() { let a = 10; \(x) { x + a } }
2021-10-31 02:05:39 -07:00
wahoo()(3) "#,
vec![
fn_decl(Signature { name: rc("wahoo"), operator: false, type_anno: None, params: vec![] },
vec![
decl(Declaration::Binding {
name: rc("a"),
constant: true,
type_anno: None,
expr: expr(NatLiteral(10))
}),
stmt(StatementKind::Expression(expr(Lambda {
params: vec![
FormalParam { name: rc("x"), default: None, anno: None }
],
type_anno: None,
body: vec![
stmt(StatementKind::Expression(binop("+", expr(Value(qn!(x))), expr(Value(qn!(a)))))),
].into()
}))),
].into()),
stmt(StatementKind::Expression(expr(Call {
f: bx(expr(Call {
f: bx(expr(Value(qn!(wahoo)))),
arguments: vec![] })),
arguments: vec![
InvocationArgument::Positional(expr(NatLiteral(3)))
]
})))
]
};
}
#[test]
fn reserved_words() {
2021-11-21 01:02:59 -08:00
//TODO assert a good error message for this
assert_fail!("module::item::call()");
2021-11-19 18:15:02 -08:00
assert_expr!("modulek::item", expr(ExpressionKind::Value(qn!(modulek, item))));
2021-10-31 02:05:39 -07:00
}
#[test]
fn type_annotations() {
use ExpressionKind::*;
use TypeIdentifier::*;
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"let a = b : Int",
vec![decl(Declaration::Binding {
name: rc("a"),
constant: true,
type_anno: None,
expr: expr_anno(Value(qn!(b)), Singleton(TypeSingletonName { name: rc("Int"), params: vec![] })),
})]
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"a: Int",
expr_anno(Value(qn!(a)), Singleton(TypeSingletonName { name: rc("Int"), params: vec![] }))
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"a: Option<Int>",
expr_anno(
Value(qn!(a)),
Singleton(TypeSingletonName {
name: rc("Option"),
params: vec![Singleton(TypeSingletonName { name: rc("Int"), params: vec![] })]
})
)
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"a: KoreanBBQSpecifier<Kimchi, Option<Bulgogi> >",
expr_anno(
Value(qn!(a)),
Singleton(TypeSingletonName {
name: rc("KoreanBBQSpecifier"),
params: vec![
Singleton(TypeSingletonName { name: rc("Kimchi"), params: vec![] }),
Singleton(TypeSingletonName {
name: rc("Option"),
params: vec![Singleton(TypeSingletonName { name: rc("Bulgogi"), params: vec![] })]
})
]
})
)
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"a: (Int, Yolo<a>)",
expr_anno(
Value(qn!(a)),
Tuple(vec![
Singleton(TypeSingletonName { name: rc("Int"), params: vec![] }),
Singleton(TypeSingletonName {
name: rc("Yolo"),
params: vec![Singleton(TypeSingletonName { name: rc("a"), params: vec![] })]
}),
]),
)
);
}
#[test]
fn type_declarations() {
use Declaration::TypeDecl;
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
"type Alpha = Alpha", vec![
decl(TypeDecl {
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
mutable: false,
2021-10-31 02:30:38 -07:00
body: TypeBody::Variants(vec![
2021-10-31 02:05:39 -07:00
Variant {
id: Default::default(),
name: rc("Alpha"),
kind: VariantKind::UnitStruct
}
])
})
]
};
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"type mut Kuah = Kuah",
decl(TypeDecl {
name: TypeSingletonName { name: rc("Kuah"), params: vec![] },
mutable: true,
2021-10-31 02:30:38 -07:00
body: TypeBody::Variants(vec![Variant {
2021-10-31 02:05:39 -07:00
id: Default::default(),
name: rc("Kuah"),
kind: VariantKind::UnitStruct
}])
})
);
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:30:38 -07:00
"type Alpha = Alpha { a: Int, b: Int }",
vec![decl(TypeDecl {
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
mutable: false,
body: TypeBody::Variants(vec![
Variant {
id: Default::default(),
name: rc("Alpha"),
kind: VariantKind::Record(vec![
(rc("a"), ty_simple("Int")),
(rc("b"), ty_simple("Int"))
])
}
])
})]
};
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:30:38 -07:00
"type Alpha = { a: Int, b: Int }",
vec![decl(TypeDecl {
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
mutable: false,
2021-11-18 18:24:06 -08:00
body: TypeBody::ImmediateRecord { id: Default::default(), fields: vec![
2021-10-31 02:30:38 -07:00
(rc("a"), ty_simple("Int")),
(rc("b"), ty_simple("Int"))
2021-11-18 18:24:06 -08:00
]}
2021-10-31 02:30:38 -07:00
})]
};
2021-10-31 02:05:39 -07:00
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"type Option<T> = None | Some(T)",
vec![decl(TypeDecl {
name: TypeSingletonName {
name: rc("Option"),
params: vec![TypeIdentifier::Singleton(TypeSingletonName { name: rc("T"), params: vec![] })]
},
mutable: false,
2021-10-31 02:30:38 -07:00
body: TypeBody::Variants(vec![
2021-10-31 02:05:39 -07:00
Variant { id: Default::default(), name: rc("None"), kind: VariantKind::UnitStruct },
Variant {
id: Default::default(),
name: rc("Some"),
kind: VariantKind::TupleStruct(vec![TypeIdentifier::Singleton(TypeSingletonName {
name: rc("T"),
params: vec![]
})])
},
])
})]
);
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"type alias Alpha = Beta",
decl(Declaration::TypeAlias { alias: rc("Alpha"), original: rc("Beta") })
);
2021-11-19 09:59:08 -08:00
assert_ast!("type Complex<T, U> = Unit | Record { field: AnotherType<Bool>, field2: (Nat, Int), field3: T } | Tuple(Int, (String, T))",
2021-10-31 02:05:39 -07:00
decl(TypeDecl {
name: TypeSingletonName { name: rc("Complex"), params: vec![
TypeIdentifier::Singleton(TypeSingletonName { name: rc("T"), params: vec![] }),
TypeIdentifier::Singleton(TypeSingletonName { name: rc("U"), params: vec![] }),
] },
mutable: false,
2021-10-31 02:30:38 -07:00
body: TypeBody::Variants(vec![
2021-10-31 02:05:39 -07:00
Variant { id: Default::default(), name: rc("Unit"), kind: VariantKind::UnitStruct },
Variant { id: Default::default(), name: rc("Record"), kind: VariantKind::Record(
vec![
(rc("field"), TypeIdentifier::Singleton(TypeSingletonName { name: rc("AnotherType"), params: vec![TypeIdentifier::Singleton(TypeSingletonName { name: rc("Bool"), params: vec![] })] })),
(rc("field2"), TypeIdentifier::Tuple(vec![
TypeIdentifier::Singleton(TypeSingletonName { name: rc("Nat"), params: vec![] }),
TypeIdentifier::Singleton(TypeSingletonName { name: rc("Int"), params: vec![] }),
]
)),
(rc("field3"), TypeIdentifier::Singleton(TypeSingletonName { name: rc("T"), params: vec![] })),
]
)},
Variant { id: Default::default(), name: rc("Tuple"), kind: VariantKind::TupleStruct(
vec![
TypeIdentifier::Singleton(TypeSingletonName { name: rc("Int"), params: vec![] }),
TypeIdentifier::Tuple(vec![
TypeIdentifier::Singleton(TypeSingletonName { name: rc("String"), params: vec![] }),
TypeIdentifier::Singleton(TypeSingletonName { name: rc("T"), params: vec![] }),
])
]
)},
]),
}));
}
2021-10-31 02:05:39 -07:00
#[test]
fn declarations() {
use ExpressionKind::*;
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"let q_q = Yolo::Swaggins",
vec![decl(Declaration::Binding {
name: rc("q_q"),
constant: true,
type_anno: None,
expr: expr(Value(qn!(Yolo, Swaggins)))
})]
);
}
#[test]
fn bindings() {
use ExpressionKind::*;
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"let mut a = 10",
vec![decl(Declaration::Binding {
name: rc("a"),
constant: false,
type_anno: None,
expr: expr(NatLiteral(10)),
})]
);
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"let a = 2 + a",
vec![stmt(StatementKind::Declaration(Declaration::Binding {
name: rc("a"),
constant: true,
type_anno: None,
expr: binop("+", expr(NatLiteral(2)), expr(Value(qn!(a)))),
}))]
);
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"let a: Nat = 2",
vec![stmt(StatementKind::Declaration(Declaration::Binding {
name: rc("a"),
constant: true,
type_anno: Some(TypeIdentifier::Singleton(TypeSingletonName { name: rc("Nat"), params: vec![] })),
expr: expr(NatLiteral(2)),
}))]
);
}
#[test]
fn functions() {
use ExpressionKind::*;
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"fn oi()",
vec![stmt(StatementKind::Declaration(Declaration::FuncSig(Signature {
name: rc("oi"),
operator: false,
params: vec![],
type_anno: None
})))]
);
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"oi()",
vec![stmt(StatementKind::Expression(expr(Call { f: bx(expr(Value(qn!(oi)))), arguments: vec![] })))]
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"oi(a, 2+2)",
expr(Call {
f: bx(expr(Value(qn!(oi)))),
arguments: vec![
InvocationArgument::Positional(expr(Value(qn!(a)))),
InvocationArgument::Positional(binop("+", expr(NatLiteral(2)), expr(NatLiteral(2)))),
]
})
);
2021-11-20 19:42:50 -08:00
let err_msg = "0: at line 1, in Alpha:\na(b,,c)\n ^\n\n1: at line 1, in Alt:\na(b,,c)\n ^\n\n2: at line 1, in token:\na(b,,c)\n ^\n\n3: at line 1, in identifier-expr:\na(b,,c)\n ^\n\n4: at line 1, in Alt:\na(b,,c)\n ^\n\n5: at line 1, in primary-expr:\na(b,,c)\n ^\n\n6: at line 1, in extended-expr:\na(b,,c)\n ^\n\n7: at line 1, in prefix-expr:\na(b,,c)\n ^\n\n8: at line 1, in expression-kind:\na(b,,c)\n ^\n\n9: at line 1, in Alt:\na(b,,c)\n ^\n\n10: at line 1, in invocation-argument:\na(b,,c)\n ^\n\n11: at line 1, in call-part:\na(b,,c)\n ^\n\n12: at line 1, in extended-expr:\na(b,,c)\n^\n\n13: at line 1, in prefix-expr:\na(b,,c)\n^\n\n14: at line 1, in expression-kind:\na(b,,c)\n^\n\n15: at line 1, in Parsing-statement:\na(b,,c)\n^\n\n16: at line 1, in AST:\na(b,,c)\n^\n\n";
2021-11-19 23:04:00 -08:00
assert_fail!("a(b,,c)", err_msg);
2021-10-31 02:05:39 -07:00
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"fn a(b, c: Int): Int",
vec![stmt(StatementKind::Declaration(Declaration::FuncSig(Signature {
name: rc("a"),
operator: false,
params: vec![
FormalParam { name: rc("b"), default: None, anno: None },
FormalParam {
name: rc("c"),
default: None,
anno: Some(TypeIdentifier::Singleton(TypeSingletonName {
name: rc("Int"),
params: vec![]
})),
},
],
type_anno: Some(TypeIdentifier::Singleton(TypeSingletonName { name: rc("Int"), params: vec![] })),
})))]
);
2021-11-11 23:41:51 -08:00
let source = r#"
fn some_function() {
}"#;
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-11-12 01:13:13 -08:00
source,
vec![fn_decl(
Signature { name: rc("some_function"), operator: false, type_anno: None, params: vec![] },
2021-11-11 23:41:51 -08:00
vec![].into()
2021-11-12 01:13:13 -08:00
)]
);
2021-10-31 02:05:39 -07:00
}
2021-11-20 23:56:53 -08:00
#[test]
fn custom_operator() {
let source = "fn (!!)(lhs,rhs)";
assert_ast!(
source,
vec![stmt(StatementKind::Declaration(Declaration::FuncSig(Signature {
name: rc("!!"),
operator: true,
params: vec![
FormalParam { name: rc("lhs"), default: None, anno: None },
FormalParam { name: rc("rhs"), default: None, anno: None },
],
type_anno: None
})))]
);
}
#[test]
fn max_function_params() {
let mut buf = "fn longfunc(".to_string();
2021-11-21 03:00:19 -08:00
for n in 0..255 {
write!(buf, "a{}, ", n).unwrap();
}
2021-11-21 03:00:19 -08:00
write!(buf, " a256").unwrap();
write!(buf, ") {{ return 20 }}").unwrap();
2021-11-19 23:04:00 -08:00
//TODO need to create a good, custom error message for this case
2021-11-21 03:00:19 -08:00
//assert_fail!(&buf, "A function cannot have more than 255 arguments");
2021-11-19 23:04:00 -08:00
assert_fail!(&buf);
2021-11-22 00:14:21 -08:00
let mut buf = r#"\("#.to_string();
for n in 0..255 {
write!(buf, "a{}, ", n).unwrap();
}
write!(buf, " a256").unwrap();
write!(buf, ") {{ return 10 }}").unwrap();
assert_fail!(&buf);
}
2021-10-31 02:05:39 -07:00
#[test]
fn functions_with_different_whitespace() {
use ExpressionKind::*;
let a = "fn a(x) { x() }";
let b = "fn a(x) {\n x() }";
let c = r#"
fn a(x) {
x()
}
"#;
for item in [a, b, c].iter() {
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
item,
vec![fn_decl(
Signature {
name: rc("a"),
operator: false,
type_anno: None,
params: vec![FormalParam { name: rc("x"), default: None, anno: None }]
},
vec![stmt(StatementKind::Expression(expr(Call {
f: bx(expr(Value(qn!(x)))),
arguments: vec![],
})))]
.into()
)]
);
}
}
2021-10-31 02:05:39 -07:00
#[test]
fn functions_with_default_args() {
use ExpressionKind::*;
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"fn func(x: Int, y: Int = 4) { }",
vec![fn_decl(
Signature {
name: rc("func"),
operator: false,
type_anno: None,
params: vec![
FormalParam { name: rc("x"), anno: Some(ty_simple("Int")), default: None },
FormalParam {
name: rc("y"),
anno: Some(ty_simple("Int")),
default: Some(expr(NatLiteral(4)))
},
],
},
vec![].into()
)]
);
}
#[test]
fn interface() {
let glue = TypeIdentifier::Singleton(TypeSingletonName { name: rc("Glue"), params: vec![] });
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"interface Unglueable { fn unglue(a: Glue); fn mar(): Glue }",
vec![decl(Declaration::Interface {
name: rc("Unglueable"),
signatures: vec![
Signature {
name: rc("unglue"),
operator: false,
params: vec![FormalParam { name: rc("a"), default: None, anno: Some(glue.clone()) },],
type_anno: None,
},
Signature { name: rc("mar"), operator: false, params: vec![], type_anno: Some(glue) },
],
})]
);
}
#[test]
2021-10-31 02:05:39 -07:00
fn impls() {
2021-11-11 22:00:04 -08:00
use Declaration::{FuncDecl, Impl};
let block = vec![
2021-11-12 01:13:13 -08:00
FuncDecl(
Signature { name: rc("yolo"), operator: false, params: vec![], type_anno: None },
vec![].into(),
),
FuncDecl(
Signature { name: rc("swagg"), operator: false, params: vec![], type_anno: None },
vec![].into(),
),
2021-11-11 22:00:04 -08:00
];
2021-10-31 02:05:39 -07:00
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-11-11 22:00:04 -08:00
"impl Heh { fn yolo() { }; fn swagg() { } }",
2021-11-12 01:13:13 -08:00
vec![decl(Impl { type_name: ty_simple("Heh"), interface_name: None, block: block.clone() })]
2021-10-31 02:05:39 -07:00
);
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-11-21 02:23:50 -08:00
"impl Heh<X> { fn yolo() { }; fn swagg() { }; }",
2021-10-31 02:05:39 -07:00
vec![decl(Impl {
type_name: TypeIdentifier::Singleton(TypeSingletonName {
name: rc("Heh"),
params: vec![ty_simple("X")]
}),
interface_name: None,
2021-11-11 22:00:04 -08:00
block: block.clone(),
2021-10-31 02:05:39 -07:00
})]
);
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-11-11 22:00:04 -08:00
"impl Heh for Saraz { fn yolo() {}; fn swagg() {} }",
2021-10-31 02:05:39 -07:00
vec![decl(Impl {
type_name: ty_simple("Saraz"),
interface_name: Some(TypeSingletonName { name: rc("Heh"), params: vec![] }),
2021-11-11 22:00:04 -08:00
block: block.clone(),
2021-10-31 02:05:39 -07:00
})]
);
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-10-31 02:05:39 -07:00
"impl Heh<T> for (Int, Codepoint) {}",
vec![decl(Impl {
type_name: TypeIdentifier::Tuple(vec![ty_simple("Int"), ty_simple("Codepoint")]),
interface_name: Some(TypeSingletonName { name: rc("Heh"), params: vec![ty_simple("T")] }),
block: vec![]
})]
);
}
#[test]
fn annotations() {
use ExpressionKind::*;
2021-11-02 16:56:12 -07:00
let func = decl(Declaration::FuncDecl(
Signature { name: rc("some_function"), operator: false, params: vec![], type_anno: None },
vec![].into(),
2021-11-02 16:56:12 -07:00
));
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
r#"
@test_annotation
fn some_function() {
}"#,
vec![decl(Declaration::Annotation {
name: rc("test_annotation"),
arguments: vec![],
inner: bx(func.clone()),
2019-10-10 18:17:59 -07:00
}),
2021-10-31 02:05:39 -07:00
]
};
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
r#"
@test_annotation(some,value)
@another_annotation
2021-10-31 02:05:39 -07:00
fn some_function() {
2021-10-31 02:05:39 -07:00
}"#,
vec![decl(Declaration::Annotation {
name: rc("test_annotation"),
arguments: vec![expr(Value(qn!(some))), expr(Value(qn!(value)))],
2021-11-02 16:56:12 -07:00
inner: bx(decl(Declaration::Annotation {
name: rc("another_annotation"), arguments: vec![], inner: bx(func)
2021-11-02 16:56:12 -07:00
}))
2019-10-10 18:17:59 -07:00
}),
2021-10-31 02:05:39 -07:00
]
};
}
#[test]
fn modules() {
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
r#"
module ephraim {
let mut a = 10
fn nah() { 33 }
}
"#,
2021-11-02 18:34:15 -07:00
vec![stmt(StatementKind::Declaration(Declaration::Module {
2021-10-31 02:05:39 -07:00
name: rc("ephraim"),
2021-11-02 18:34:15 -07:00
items: vec![
2021-10-31 02:05:39 -07:00
decl(Declaration::Binding {
name: rc("a"), constant: false, type_anno: None,
expr: expr(ExpressionKind::NatLiteral(10))
}),
fn_decl(Signature { name: rc("nah"), operator: false, params: vec![], type_anno: None },
vec![stmt(StatementKind::Expression(expr(ExpressionKind::NatLiteral(33))))].into()),
].into()
}))]
};
}
2021-10-31 02:05:39 -07:00
#[test]
fn imports() {
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
"import harbinger::draughts::Norgleheim",
vec![stmt(StatementKind::Import(ImportSpecifier {
id: ItemId::default(),
path_components: vec![rc("harbinger"), rc("draughts"), rc("Norgleheim")],
imported_names: ImportedNames::LastOfPath
}))]
};
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
"import harbinger::draughts::{Norgleheim, Xraksenlaigar}",
vec![stmt(StatementKind::Import(ImportSpecifier {
id: ItemId::default(),
path_components: vec![rc("harbinger"), rc("draughts")],
imported_names: ImportedNames::List(vec![
rc("Norgleheim"), rc("Xraksenlaigar")])
}))]
};
2021-11-21 02:30:45 -08:00
assert_fail!("import bespouri::{}");
2021-10-31 02:05:39 -07:00
2021-11-19 09:59:08 -08:00
assert_ast! {
2021-10-31 02:05:39 -07:00
"import bespouri::*",
vec![stmt(StatementKind::Import(ImportSpecifier {
id: Default::default(),
path_components: vec![rc("bespouri")],
imported_names: ImportedNames::All,
}))]
};
}
#[test]
fn if_exprs() {
use ExpressionKind::*;
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"if a() then { tuah(); }",
expr(IfExpression {
discriminator: Some(bx(expr(Call { f: bx(expr(Value(qn!(a)))), arguments: vec![] }))),
body: bx(IfExpressionBody::SimpleConditional {
then_case: vec![exst(Call { f: bx(expr(Value(qn!(tuah)))), arguments: vec![] })].into(),
else_case: None,
})
})
);
2021-11-19 00:40:10 -08:00
//TODO add tests for named expressions
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"if a then b else c",
expr(IfExpression {
discriminator: Some(bx(expr(Value(qn!(a))))),
body: bx(IfExpressionBody::SimpleConditional {
then_case: vec![exst(Value(qn!(b)))].into(),
else_case: Some(vec![exst(Value(qn!(c)))].into()),
})
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-11-19 00:40:10 -08:00
r#"if true then {
2021-10-31 02:05:39 -07:00
let a = 10
b
} else {
c
}"#,
2021-10-31 02:05:39 -07:00
expr(IfExpression {
discriminator: Some(bx(expr(BoolLiteral(true)))),
body: bx(IfExpressionBody::SimpleConditional {
then_case: vec![
decl(Declaration::Binding {
name: rc("a"),
constant: true,
type_anno: None,
expr: expr(NatLiteral(10))
}),
exst(Value(qn!(b))),
]
.into(),
else_case: Some(vec![exst(Value(qn!(c))),].into())
})
})
);
}
2021-10-31 02:05:39 -07:00
#[test]
fn pattern_matching() {
use ExpressionKind::*;
2021-10-31 02:05:39 -07:00
for item in ["if x is Some(a) then { 4 } else { 9 }", "if x is Some(a) then 4 else 9"] {
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
item,
expr(IfExpression {
discriminator: Some(bx(expr(Value(qn!(x))))),
body: bx(IfExpressionBody::SimplePatternMatch {
pattern: Pattern::TupleStruct(qn!(Some), vec![Pattern::VarOrName(qn!(a))]),
then_case: vec![exst(NatLiteral(4))].into(),
else_case: Some(vec![exst(NatLiteral(9))].into()),
})
})
);
}
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"if x is Something { a, b: x } then { 4 } else { 9 }",
expr(IfExpression {
discriminator: Some(bx(expr(Value(qn!(x))))),
body: bx(IfExpressionBody::SimplePatternMatch {
pattern: Pattern::Record(
qn!(Something),
2021-11-01 13:46:38 -07:00
vec![(rc("a"), Pattern::VarOrName(qn!(a))), (rc("b"), Pattern::VarOrName(qn!(x)))]
2021-10-31 02:05:39 -07:00
),
then_case: vec![exst(NatLiteral(4))].into(),
else_case: Some(vec![exst(NatLiteral(9))].into()),
})
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"if x is -1 then 1 else 2",
expr(IfExpression {
discriminator: Some(bx(expr(Value(qn!(x))))),
body: bx(IfExpressionBody::SimplePatternMatch {
pattern: Pattern::Literal(PatternLiteral::NumPattern { neg: true, num: NatLiteral(1) }),
then_case: vec![exst(NatLiteral(1))].into(),
else_case: Some(vec![exst(NatLiteral(2))].into()),
})
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
"if x is true then 1 else 2",
expr(IfExpression {
discriminator: Some(bx(expr(Value(qn!(x))))),
body: bx(IfExpressionBody::SimplePatternMatch {
pattern: Pattern::Literal(PatternLiteral::BoolPattern(true)),
then_case: vec![exst(NatLiteral(1))].into(),
else_case: Some(vec![exst(NatLiteral(2))].into()),
})
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-11-11 22:24:35 -08:00
"if x { is 1 then 5; else 20 }",
2021-10-31 02:05:39 -07:00
expr(IfExpression {
discriminator: Some(bx(expr(Value(qn!(x))))),
body: bx(IfExpressionBody::CondList(vec![
ConditionArm {
condition: Condition::Pattern(Pattern::Literal(PatternLiteral::NumPattern {
neg: false,
num: NatLiteral(1)
})),
guard: None,
body: vec![exst(NatLiteral(5))].into(),
},
ConditionArm {
condition: Condition::Else,
guard: None,
body: vec![exst(NatLiteral(20))].into(),
},
]))
})
);
2021-11-19 01:35:25 -08:00
assert_expr!(
2021-10-31 02:05:39 -07:00
r#"if x is "gnosticism" then 1 else 2"#,
expr(IfExpression {
discriminator: Some(bx(expr(Value(qn!(x))))),
body: bx(IfExpressionBody::SimplePatternMatch {
pattern: Pattern::Literal(PatternLiteral::StringPattern(rc("gnosticism"))),
then_case: vec![exst(NatLiteral(1))].into(),
else_case: Some(vec![exst(NatLiteral(2))].into()),
})
})
);
2021-11-19 01:35:25 -08:00
assert_expr! {
2021-10-31 02:05:39 -07:00
r#"
if (45, "panda", false, 2.2) {
2021-11-11 22:24:35 -08:00
is (49, "pablo", _, 28.4) then "no"
2021-10-31 02:05:39 -07:00
is (_, "panda", _, -2.2) then "yes"
is _ then "maybe"
}"#,
expr(
IfExpression {
discriminator: Some(bx(expr(TupleLiteral(vec![
2021-11-21 01:02:59 -08:00
expr(NatLiteral(45)), expr(strlit("panda")), expr(BoolLiteral(false)), expr(FloatLiteral(2.2))
2021-10-31 02:05:39 -07:00
])))),
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-11-21 01:02:59 -08:00
body: vec![stmt(StatementKind::Expression(expr(strlit("no"))))].into(),
2021-10-31 02:05:39 -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-11-21 01:02:59 -08:00
body: vec![stmt(StatementKind::Expression(expr(strlit("yes"))))].into(),
2021-10-31 02:05:39 -07:00
},
ConditionArm {
condition: Condition::Pattern(Pattern::Ignored),
guard: None,
2021-11-21 01:02:59 -08:00
body: vec![exst(strlit("maybe"))].into(),
2021-10-31 02:05:39 -07:00
},
]))
}
)
};
2021-10-26 00:39:24 -07:00
}
2021-11-01 00:14:15 -07:00
#[test]
fn flow_control() {
use ExpressionKind::*;
2021-11-19 01:01:26 -08:00
// This is an incorrect program, but should parse correctly.
2021-11-01 00:14:15 -07:00
let source = r#"
fn test() {
let a = 10;
break;
continue;
return;
return 10;
}"#;
2021-11-19 09:59:08 -08:00
assert_ast!(
2021-11-01 00:14:15 -07:00
source,
vec![fn_decl(
Signature { name: rc("test"), operator: false, type_anno: None, params: vec![] },
vec![
decl(Declaration::Binding {
name: rc("a"),
constant: true,
type_anno: None,
expr: expr(NatLiteral(10))
}),
stmt(StatementKind::Flow(FlowControl::Break)),
stmt(StatementKind::Flow(FlowControl::Continue)),
stmt(StatementKind::Flow(FlowControl::Return(None))),
stmt(StatementKind::Flow(FlowControl::Return(Some(expr(NatLiteral(10)))))),
]
.into()
)]
);
}
2021-11-06 20:33:33 -07:00
#[test]
fn blocks() {
use ExpressionKind::*;
let cases = ["{ a }", "{ a; }", "{a}", "{ a\n }", "{ a\n\n }", "{ a;\n\n; }"];
for case in cases.iter() {
2021-11-20 23:00:19 -08:00
assert_block!(case, vec![exst(Value(qn!(a)))].into());
2021-11-06 20:33:33 -07:00
}
2021-11-14 00:34:21 -08:00
let source = r#"{
fn quah() {
fn foo() { }
}
}"#;
2021-11-20 23:00:19 -08:00
assert_block!(
source,
2021-11-14 00:34:21 -08:00
vec![decl(Declaration::FuncDecl(
Signature { name: rc("quah"), operator: false, params: vec![], type_anno: None },
vec![decl(Declaration::FuncDecl(
Signature { name: rc("foo"), operator: false, params: vec![], type_anno: None },
vec![].into(),
))]
.into()
))]
.into()
);
2021-11-18 01:37:05 -08:00
2021-11-20 23:00:19 -08:00
assert_block!("{}", vec![].into());
2021-11-18 01:37:05 -08:00
let source = r#"{
//hella
4_5 //bog
11; /*chutney*/0xf
}"#;
2021-11-22 01:52:08 -08:00
assert_block!(
source,
2021-11-18 01:37:05 -08:00
vec![
Statement {
id: Default::default(),
location: Default::default(),
kind: StatementKind::Expression(Expression::new(
Default::default(),
ExpressionKind::NatLiteral(45)
))
},
Statement {
id: Default::default(),
location: Default::default(),
kind: StatementKind::Expression(Expression::new(
Default::default(),
ExpressionKind::NatLiteral(11)
))
},
Statement {
id: Default::default(),
location: Default::default(),
kind: StatementKind::Expression(Expression::new(
Default::default(),
ExpressionKind::NatLiteral(15)
))
},
]
.into()
);
2021-11-06 20:33:33 -07:00
}
2021-11-13 01:41:17 -08:00
#[test]
fn comments() {
use ExpressionKind::*;
let source = "1 + /* hella /* bro */ */ 2";
2021-11-20 22:55:11 -08:00
assert_expr!(source, binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))));
2021-11-13 01:41:17 -08:00
//TODO make sure this error message makes sense
let source = "1 + /* hella /* bro */ 2";
2021-11-20 22:55:11 -08:00
assert_fail_expr!(source, "foo");
2021-11-13 01:41:17 -08:00
2021-11-20 02:03:28 -08:00
let source = "1 + /* hella */ bro */ 2";
assert_fail_expr!(source, binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))));
2021-11-13 13:18:02 -08:00
let source = "5//no man\n";
2021-11-20 22:55:11 -08:00
assert_ast!(source, vec![exst(NatLiteral(5))]);
2021-11-19 09:59:08 -08:00
let source = " /*yolo*/ barnaby";
2021-11-20 22:55:11 -08:00
assert_ast!(source, exst(ExpressionKind::Value(qn!(barnaby))));
2021-11-13 01:41:17 -08:00
}
2021-11-13 13:45:52 -08:00
//TODO support backtick operators like this
/*
#[test]
fn backtick_operators() {
let output = token_kinds("1 `plus` 2");
assert_eq!(output, vec![digit!("1"), op!("plus"), digit!("2")]);
}
*/