Move rest of parse tests over to new format
This commit is contained in:
parent
8db9176fce
commit
81bfe22974
@ -117,7 +117,7 @@ pub enum Declaration {
|
|||||||
FuncSig(Signature),
|
FuncSig(Signature),
|
||||||
FuncDecl(Signature, Block),
|
FuncDecl(Signature, Block),
|
||||||
TypeDecl { name: TypeSingletonName, body: TypeBody, mutable: bool },
|
TypeDecl { name: TypeSingletonName, body: TypeBody, mutable: bool },
|
||||||
//TODO this needs to be more sophisticated
|
//TODO TypeAlias `original` needs to be a more complex type definition
|
||||||
TypeAlias { alias: Rc<String>, original: Rc<String> },
|
TypeAlias { alias: Rc<String>, original: Rc<String> },
|
||||||
Binding { name: Rc<String>, constant: bool, type_anno: Option<TypeIdentifier>, expr: Expression },
|
Binding { name: Rc<String>, constant: bool, type_anno: Option<TypeIdentifier>, expr: Expression },
|
||||||
Impl { type_name: TypeIdentifier, interface_name: Option<TypeSingletonName>, block: Vec<Declaration> },
|
Impl { type_name: TypeIdentifier, interface_name: Option<TypeSingletonName>, block: Vec<Declaration> },
|
||||||
@ -133,6 +133,7 @@ pub struct Signature {
|
|||||||
pub type_anno: Option<TypeIdentifier>,
|
pub type_anno: Option<TypeIdentifier>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO I can probably get rid of TypeBody
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct TypeBody(pub Vec<Variant>);
|
pub struct TypeBody(pub Vec<Variant>);
|
||||||
|
|
||||||
@ -158,6 +159,7 @@ pub struct Expression {
|
|||||||
#[derivative(PartialEq = "ignore")]
|
#[derivative(PartialEq = "ignore")]
|
||||||
pub id: ItemId,
|
pub id: ItemId,
|
||||||
pub kind: ExpressionKind,
|
pub kind: ExpressionKind,
|
||||||
|
//TODO this should only allow singletons, not tuples
|
||||||
pub type_anno: Option<TypeIdentifier>,
|
pub type_anno: Option<TypeIdentifier>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -689,6 +689,13 @@ impl Parser {
|
|||||||
|
|
||||||
#[recursive_descent_method]
|
#[recursive_descent_method]
|
||||||
fn prefix_expr(&mut self) -> ParseResult<Expression> {
|
fn prefix_expr(&mut self) -> ParseResult<Expression> {
|
||||||
|
loop {
|
||||||
|
match self.token_handler.peek_kind() {
|
||||||
|
Semicolon | Newline => { self.token_handler.next(); },
|
||||||
|
_ => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match self.token_handler.peek_kind() {
|
match self.token_handler.peek_kind() {
|
||||||
Operator(ref op) if PrefixOp::is_prefix(&*op) => {
|
Operator(ref op) if PrefixOp::is_prefix(&*op) => {
|
||||||
let sigil = match self.token_handler.next().kind {
|
let sigil = match self.token_handler.next().kind {
|
||||||
|
@ -33,6 +33,14 @@ fn stmt(kind: StatementKind) -> Statement {
|
|||||||
Statement { location: Location::default(), id: ItemId::default(), kind }
|
Statement { location: Location::default(), id: ItemId::default(), kind }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exst(kind: ExpressionKind) -> Statement {
|
||||||
|
Statement {
|
||||||
|
location: Location::default(),
|
||||||
|
id: ItemId::default(),
|
||||||
|
kind: StatementKind::Expression(expr(kind)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn decl(declaration: Declaration) -> Statement {
|
fn decl(declaration: Declaration) -> Statement {
|
||||||
Statement {
|
Statement {
|
||||||
location: Location::default(),
|
location: Location::default(),
|
||||||
@ -85,8 +93,8 @@ macro_rules! qn {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn int_anno() -> TypeIdentifier {
|
fn ty_simple(name: &str) -> TypeIdentifier {
|
||||||
TypeIdentifier::Singleton(TypeSingletonName { name: rc("Int"), params: vec![] })
|
TypeIdentifier::Singleton(TypeSingletonName { name: rc(name), params: vec![] })
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! assert_ast {
|
macro_rules! assert_ast {
|
||||||
@ -136,6 +144,14 @@ fn basic_literals() {
|
|||||||
assert_expr!(r#""hello""#, expr(StringLiteral(rc("hello"))));
|
assert_expr!(r#""hello""#, expr(StringLiteral(rc("hello"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn list_literals() {
|
||||||
|
use ExpressionKind::*;
|
||||||
|
|
||||||
|
assert_expr!("[]", expr(ListLiteral(vec![])));
|
||||||
|
assert_expr!("[1,2]", expr(ListLiteral(vec![expr(NatLiteral(1)), expr(NatLiteral(2)),])));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn binexps() {
|
fn binexps() {
|
||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
@ -374,7 +390,7 @@ fn lambda_expressions() {
|
|||||||
r#"\ (x: Int, y) { a;b;c;}"#,
|
r#"\ (x: Int, y) { a;b;c;}"#,
|
||||||
expr(Lambda {
|
expr(Lambda {
|
||||||
params: vec![
|
params: vec![
|
||||||
FormalParam { name: rc!(x), anno: Some(int_anno()), default: None },
|
FormalParam { name: rc!(x), anno: Some(ty_simple("Int")), default: None },
|
||||||
FormalParam { name: rc!(y), anno: None, default: None },
|
FormalParam { name: rc!(y), anno: None, default: None },
|
||||||
],
|
],
|
||||||
type_anno: None,
|
type_anno: None,
|
||||||
@ -402,7 +418,7 @@ fn lambda_expressions() {
|
|||||||
assert_expr!(
|
assert_expr!(
|
||||||
r#"\(x: Int): String { "q" }"#,
|
r#"\(x: Int): String { "q" }"#,
|
||||||
expr(Lambda {
|
expr(Lambda {
|
||||||
params: vec![FormalParam { name: rc!(x), anno: Some(int_anno()), default: None },],
|
params: vec![FormalParam { name: rc!(x), anno: Some(ty_simple("Int")), default: None },],
|
||||||
type_anno: Some(TypeIdentifier::Singleton(TypeSingletonName {
|
type_anno: Some(TypeIdentifier::Singleton(TypeSingletonName {
|
||||||
name: rc("String"),
|
name: rc("String"),
|
||||||
params: vec![]
|
params: vec![]
|
||||||
@ -433,7 +449,7 @@ fn single_param_lambda() {
|
|||||||
assert_expr!(
|
assert_expr!(
|
||||||
r#"\x: Int { x + 10 }"#,
|
r#"\x: Int { x + 10 }"#,
|
||||||
expr(Lambda {
|
expr(Lambda {
|
||||||
params: vec![FormalParam { name: rc!(x), anno: Some(int_anno()), default: None },],
|
params: vec![FormalParam { name: rc!(x), anno: Some(ty_simple("Int")), default: None },],
|
||||||
type_anno: None,
|
type_anno: None,
|
||||||
body: vec![stmt(StatementKind::Expression(binop(
|
body: vec![stmt(StatementKind::Expression(binop(
|
||||||
"+",
|
"+",
|
||||||
@ -548,18 +564,131 @@ fn type_annotations() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn type_declarations() {
|
||||||
|
use Declaration::TypeDecl;
|
||||||
|
assert_ast! {
|
||||||
|
"type Alpha = Alpha", vec![
|
||||||
|
decl(TypeDecl {
|
||||||
|
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
|
||||||
|
mutable: false,
|
||||||
|
body: TypeBody(vec![
|
||||||
|
Variant {
|
||||||
|
id: Default::default(),
|
||||||
|
name: rc("Alpha"),
|
||||||
|
kind: VariantKind::UnitStruct
|
||||||
|
}
|
||||||
|
])
|
||||||
|
})
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_ast!(
|
||||||
|
"type mut Kuah = Kuah",
|
||||||
|
decl(TypeDecl {
|
||||||
|
name: TypeSingletonName { name: rc("Kuah"), params: vec![] },
|
||||||
|
mutable: true,
|
||||||
|
body: TypeBody(vec![Variant {
|
||||||
|
id: Default::default(),
|
||||||
|
name: rc("Kuah"),
|
||||||
|
kind: VariantKind::UnitStruct
|
||||||
|
}])
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
//TODO support this
|
||||||
|
let specs = ["type Alpha = Alpha { a: Int, b: Int }" /* "type Alpha = { a: Int, b: Int }"*/];
|
||||||
|
for spec in specs {
|
||||||
|
assert_ast! {
|
||||||
|
spec, vec![decl(TypeDecl {
|
||||||
|
name: TypeSingletonName { name: rc("Alpha"), params: vec![] },
|
||||||
|
mutable: false,
|
||||||
|
body: TypeBody(vec![
|
||||||
|
Variant {
|
||||||
|
id: Default::default(),
|
||||||
|
name: rc("Alpha"),
|
||||||
|
kind: VariantKind::Record(vec![
|
||||||
|
(rc("a"), ty_simple("Int")),
|
||||||
|
(rc("b"), ty_simple("Int"))
|
||||||
|
])
|
||||||
|
}
|
||||||
|
])
|
||||||
|
})]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_ast!(
|
||||||
|
"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,
|
||||||
|
body: TypeBody(vec![
|
||||||
|
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![]
|
||||||
|
})])
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})]
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_ast!(
|
||||||
|
"type alias Alpha = Beta",
|
||||||
|
decl(Declaration::TypeAlias { alias: rc("Alpha"), original: rc("Beta") })
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_ast!("type Complex<T, U> = Unit | Record { field: AnotherType<Bool>, field2: (Nat, Int), field3: T } | Tuple(Int, (String, T))",
|
||||||
|
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,
|
||||||
|
body: TypeBody(vec![
|
||||||
|
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![] }),
|
||||||
|
])
|
||||||
|
]
|
||||||
|
)},
|
||||||
|
]),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn declarations() {
|
fn declarations() {
|
||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
|
|
||||||
assert_ast!(
|
assert_ast!(
|
||||||
"let q_q = Yolo::Swaggins",
|
"let q_q = Yolo::Swaggins",
|
||||||
vec![stmt(StatementKind::Declaration(Declaration::Binding {
|
vec![decl(Declaration::Binding {
|
||||||
name: rc("q_q"),
|
name: rc("q_q"),
|
||||||
constant: true,
|
constant: true,
|
||||||
type_anno: None,
|
type_anno: None,
|
||||||
expr: expr(Value(qn!(Yolo, Swaggins)))
|
expr: expr(Value(qn!(Yolo, Swaggins)))
|
||||||
}))]
|
})]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,8 +828,12 @@ fn functions_with_default_args() {
|
|||||||
operator: false,
|
operator: false,
|
||||||
type_anno: None,
|
type_anno: None,
|
||||||
params: vec![
|
params: vec![
|
||||||
FormalParam { name: rc("x"), anno: Some(int_anno()), default: None },
|
FormalParam { name: rc("x"), anno: Some(ty_simple("Int")), default: None },
|
||||||
FormalParam { name: rc("y"), anno: Some(int_anno()), default: Some(expr(NatLiteral(4))) },
|
FormalParam {
|
||||||
|
name: rc("y"),
|
||||||
|
anno: Some(ty_simple("Int")),
|
||||||
|
default: Some(expr(NatLiteral(4)))
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
vec![].into()
|
vec![].into()
|
||||||
@ -728,6 +861,59 @@ fn interface() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn impls() {
|
||||||
|
use Declaration::{FuncSig, Impl};
|
||||||
|
|
||||||
|
assert_ast!(
|
||||||
|
"impl Heh { fn yolo(); fn swagg(); }",
|
||||||
|
vec![decl(Impl {
|
||||||
|
type_name: ty_simple("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 })
|
||||||
|
]
|
||||||
|
})]
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_ast!(
|
||||||
|
"impl Heh<X> { fn yolo(); fn swagg(); }",
|
||||||
|
vec![decl(Impl {
|
||||||
|
type_name: TypeIdentifier::Singleton(TypeSingletonName {
|
||||||
|
name: rc("Heh"),
|
||||||
|
params: vec![ty_simple("X")]
|
||||||
|
}),
|
||||||
|
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 })
|
||||||
|
]
|
||||||
|
})]
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_ast!(
|
||||||
|
"impl Heh for Saraz { fn yolo(); fn swagg(); }",
|
||||||
|
vec![decl(Impl {
|
||||||
|
type_name: ty_simple("Saraz"),
|
||||||
|
interface_name: Some(TypeSingletonName { name: rc("Heh"), 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 })
|
||||||
|
]
|
||||||
|
})]
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_ast!(
|
||||||
|
"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]
|
#[test]
|
||||||
fn annotations() {
|
fn annotations() {
|
||||||
use ExpressionKind::*;
|
use ExpressionKind::*;
|
||||||
@ -825,3 +1011,197 @@ fn imports() {
|
|||||||
}))]
|
}))]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn if_exprs() {
|
||||||
|
use ExpressionKind::*;
|
||||||
|
assert_expr!(
|
||||||
|
"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,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_expr!(
|
||||||
|
"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()),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_expr!(
|
||||||
|
r#"
|
||||||
|
if true then {
|
||||||
|
let a = 10
|
||||||
|
b
|
||||||
|
} else {
|
||||||
|
c
|
||||||
|
}"#,
|
||||||
|
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())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pattern_matching() {
|
||||||
|
use ExpressionKind::*;
|
||||||
|
|
||||||
|
for item in ["if x is Some(a) then { 4 } else { 9 }", "if x is Some(a) then 4 else 9"] {
|
||||||
|
assert_expr!(
|
||||||
|
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()),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_expr!(
|
||||||
|
"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),
|
||||||
|
vec![
|
||||||
|
(rc("a"), Pattern::Literal(PatternLiteral::StringPattern(rc("a")))),
|
||||||
|
(rc("b"), Pattern::VarOrName(qn!(x)))
|
||||||
|
]
|
||||||
|
),
|
||||||
|
then_case: vec![exst(NatLiteral(4))].into(),
|
||||||
|
else_case: Some(vec![exst(NatLiteral(9))].into()),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_expr!(
|
||||||
|
"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()),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_expr!(
|
||||||
|
"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()),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_expr!(
|
||||||
|
"if x { is 1 then 5, else 20 }",
|
||||||
|
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(),
|
||||||
|
},
|
||||||
|
]))
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_expr!(
|
||||||
|
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()),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_expr! {
|
||||||
|
r#"
|
||||||
|
if (45, "panda", false, 2.2) {
|
||||||
|
is (49, "pablo", _, 28.4) then "no"
|
||||||
|
is (_, "panda", _, -2.2) then "yes"
|
||||||
|
is _ then "maybe"
|
||||||
|
}"#,
|
||||||
|
expr(
|
||||||
|
IfExpression {
|
||||||
|
discriminator: Some(bx(expr(TupleLiteral(vec![
|
||||||
|
expr(NatLiteral(45)), expr(StringLiteral(rc("panda"))), expr(BoolLiteral(false)), expr(FloatLiteral(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,
|
||||||
|
body: vec![stmt(StatementKind::Expression(expr(StringLiteral(rc("no")))))].into(),
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
body: vec![stmt(StatementKind::Expression(expr(StringLiteral(rc("yes")))))].into(),
|
||||||
|
},
|
||||||
|
ConditionArm {
|
||||||
|
condition: Condition::Pattern(Pattern::Ignored),
|
||||||
|
guard: None,
|
||||||
|
body: vec![exst(StringLiteral(rc("maybe")))].into(),
|
||||||
|
},
|
||||||
|
]))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
@ -100,48 +100,6 @@ macro_rules! exst {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn parsing_types() {
|
|
||||||
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} ));
|
|
||||||
parse_test_wrap_ast!("type alias Sex = Drugs", decl!(TypeAlias { alias: rc!(Sex), original: rc!(Drugs) }));
|
|
||||||
parse_test_wrap_ast!("type Sanchez = Miguel | Alejandro(Int, Option<a>) | Esperanza { a: Int, b: String }",
|
|
||||||
decl!(TypeDecl {
|
|
||||||
name: tys!("Sanchez"),
|
|
||||||
body: TypeBody(vec![
|
|
||||||
Variant {
|
|
||||||
id: ItemId::default(),
|
|
||||||
kind: UnitStruct, name: rc!(Miguel) },
|
|
||||||
Variant {
|
|
||||||
id: ItemId::default(),
|
|
||||||
name: rc!(Alejandro),
|
|
||||||
kind: TupleStruct(vec![
|
|
||||||
Singleton(TypeSingletonName { name: rc!(Int), params: vec![] }),
|
|
||||||
Singleton(TypeSingletonName { name: rc!(Option), params: vec![Singleton(TypeSingletonName { name: rc!(a), params: vec![] })] }),
|
|
||||||
])
|
|
||||||
},
|
|
||||||
Variant {
|
|
||||||
id: ItemId::default(),
|
|
||||||
name: rc!(Esperanza),
|
|
||||||
kind: Record(vec![
|
|
||||||
(rc!(a), Singleton(TypeSingletonName { name: rc!(Int), params: vec![] })),
|
|
||||||
(rc!(b), Singleton(TypeSingletonName { name: rc!(String), params: vec![] })),
|
|
||||||
])
|
|
||||||
}
|
|
||||||
]),
|
|
||||||
mutable: false
|
|
||||||
}));
|
|
||||||
|
|
||||||
parse_test_wrap_ast! {
|
|
||||||
"type Jorge<a> = Diego | Kike(a)",
|
|
||||||
decl!(TypeDecl{
|
|
||||||
name: TypeSingletonName { name: rc!(Jorge), params: vec![Singleton(TypeSingletonName { name: rc!(a), params: vec![] })] },
|
|
||||||
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![] })]) }]),
|
|
||||||
mutable: false
|
|
||||||
}
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parsing_block_expressions() {
|
fn parsing_block_expressions() {
|
||||||
@ -212,227 +170,4 @@ fn parsing_block_expressions() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parsing_impls() {
|
fn parsing_impls() {
|
||||||
parse_test_wrap_ast!("impl Heh { fn yolo(); fn swagg(); }",
|
|
||||||
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 })
|
|
||||||
] }));
|
|
||||||
|
|
||||||
parse_test_wrap_ast!("impl Mondai for Lollerino { fn yolo(); fn swagg(); }",
|
|
||||||
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 })
|
|
||||||
] }));
|
|
||||||
|
|
||||||
parse_test_wrap_ast!("impl Hella<T> for (Alpha, Omega) { }",
|
|
||||||
decl!(Impl {
|
|
||||||
type_name: Tuple(vec![ty!("Alpha"), ty!("Omega")]),
|
|
||||||
interface_name: Some(TypeSingletonName { name: rc!(Hella), params: vec![ty!("T")] }),
|
|
||||||
block: vec![]
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
parse_test_wrap_ast!("impl Option<WTFMate> { fn oi() }",
|
|
||||||
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 }),
|
|
||||||
]
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn list_literals() {
|
|
||||||
parse_test_wrap_ast! {
|
|
||||||
"[1,2]",
|
|
||||||
exst!(ListLiteral(vec![ex!(NatLiteral(1)), ex!(NatLiteral(2))]))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn patterns() {
|
|
||||||
parse_test_wrap_ast! {
|
|
||||||
"if x is Some(a) then { 4 } else { 9 }", exst!(
|
|
||||||
IfExpression {
|
|
||||||
discriminator: Some(bx!(ex!(s "x"))),
|
|
||||||
body: bx!(IfExpressionBody::SimplePatternMatch {
|
|
||||||
pattern: Pattern::TupleStruct(qname!(Some), vec![Pattern::VarOrName(qname!(a))]),
|
|
||||||
then_case: vec![exst!(s "4")].into(),
|
|
||||||
else_case: Some(vec![exst!(s "9")].into()) })
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_test_wrap_ast! {
|
|
||||||
"if x is Some(a) then 4 else 9", exst!(
|
|
||||||
IfExpression {
|
|
||||||
discriminator: Some(bx!(ex!(s "x"))),
|
|
||||||
body: bx!(IfExpressionBody::SimplePatternMatch {
|
|
||||||
pattern: Pattern::TupleStruct(qname!(Some), vec![Pattern::VarOrName(qname!(a))]),
|
|
||||||
then_case: vec![exst!(s "4")].into(),
|
|
||||||
else_case: Some(vec![exst!(s "9")].into()) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_test_wrap_ast! {
|
|
||||||
"if x is Something { a, b: x } then { 4 } else { 9 }", exst!(
|
|
||||||
IfExpression {
|
|
||||||
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)))
|
|
||||||
]),
|
|
||||||
then_case: vec![exst!(s "4")].into(),
|
|
||||||
else_case: Some(vec![exst!(s "9")].into())
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn pattern_literals() {
|
|
||||||
parse_test_wrap_ast! {
|
|
||||||
"if x is -1 then 1 else 2",
|
|
||||||
exst!(
|
|
||||||
IfExpression {
|
|
||||||
discriminator: Some(bx!(ex!(s "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()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_test_wrap_ast! {
|
|
||||||
"if x is 1 then 1 else 2",
|
|
||||||
exst!(
|
|
||||||
IfExpression {
|
|
||||||
discriminator: Some(bx!(ex!(s "x"))),
|
|
||||||
body: bx!(IfExpressionBody::SimplePatternMatch {
|
|
||||||
pattern: Pattern::Literal(PatternLiteral::NumPattern { neg: false, num: NatLiteral(1) }),
|
|
||||||
then_case: vec![exst!(s "1")].into(),
|
|
||||||
else_case: Some(vec![exst!(s "2")].into()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_test_wrap_ast! {
|
|
||||||
"if x is true then 1 else 2",
|
|
||||||
exst!(
|
|
||||||
IfExpression {
|
|
||||||
discriminator: Some(bx!(ex!(s "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()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_test_wrap_ast! {
|
|
||||||
"if x is \"gnosticism\" then 1 else 2",
|
|
||||||
exst!(
|
|
||||||
IfExpression {
|
|
||||||
discriminator: Some(bx!(ex!(s "x"))),
|
|
||||||
body: bx!(IfExpressionBody::SimplePatternMatch {
|
|
||||||
pattern: Pattern::Literal(PatternLiteral::StringPattern(rc!(gnosticism))),
|
|
||||||
then_case: vec![exst!(s "1")].into(),
|
|
||||||
else_case: Some(vec![exst!(s "2")].into()),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn if_expr() {
|
|
||||||
parse_test_wrap_ast! {
|
|
||||||
"if x { is 1 then 5, else 20 }",
|
|
||||||
exst! {
|
|
||||||
IfExpression {
|
|
||||||
discriminator: Some(bx!(ex!(s "x"))),
|
|
||||||
body: bx!(IfExpressionBody::CondList(
|
|
||||||
vec![
|
|
||||||
ConditionArm {
|
|
||||||
condition: Condition::Pattern(Pattern::Literal(PatternLiteral::NumPattern { neg: false, num: NatLiteral(1)})),
|
|
||||||
guard: None,
|
|
||||||
body: vec![exst!(s "5")].into(),
|
|
||||||
},
|
|
||||||
ConditionArm {
|
|
||||||
condition: Condition::Else,
|
|
||||||
guard: None,
|
|
||||||
body: vec![exst!(s "20")].into(),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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,
|
|
||||||
body: vec![exst!(s r#""no""#)].into(),
|
|
||||||
},
|
|
||||||
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,
|
|
||||||
body: vec![exst!(s r#""yes""#)].into(),
|
|
||||||
},
|
|
||||||
ConditionArm {
|
|
||||||
condition: Condition::Pattern(Pattern::Ignored),
|
|
||||||
guard: None,
|
|
||||||
body: vec![exst!(s r#""maybe""#)].into(),
|
|
||||||
},
|
|
||||||
]))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user