Compare commits

...

2 Commits

Author SHA1 Message Date
Greg Shuflin
663e99df23 Rename back to test.rs 2021-10-31 02:05:39 -07:00
Greg Shuflin
81bfe22974 Move rest of parse tests over to new format 2021-10-31 02:04:28 -07:00
4 changed files with 1136 additions and 1186 deletions

View File

@ -117,7 +117,7 @@ pub enum Declaration {
FuncSig(Signature),
FuncDecl(Signature, Block),
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> },
Binding { name: Rc<String>, constant: bool, type_anno: Option<TypeIdentifier>, expr: Expression },
Impl { type_name: TypeIdentifier, interface_name: Option<TypeSingletonName>, block: Vec<Declaration> },
@ -133,6 +133,7 @@ pub struct Signature {
pub type_anno: Option<TypeIdentifier>,
}
//TODO I can probably get rid of TypeBody
#[derive(Debug, PartialEq, Clone)]
pub struct TypeBody(pub Vec<Variant>);
@ -158,6 +159,7 @@ pub struct Expression {
#[derivative(PartialEq = "ignore")]
pub id: ItemId,
pub kind: ExpressionKind,
//TODO this should only allow singletons, not tuples
pub type_anno: Option<TypeIdentifier>,
}

View File

@ -166,7 +166,6 @@
//!
//! module := 'module' IDENTIFIER '{' statement* '}'
//! ```
mod new_tests;
mod test;
use std::rc::Rc;
@ -689,6 +688,13 @@ impl Parser {
#[recursive_descent_method]
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() {
Operator(ref op) if PrefixOp::is_prefix(&*op) => {
let sigil = match self.token_handler.next().kind {

View File

@ -1,827 +0,0 @@
#![cfg(test)]
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::vec_init_then_push)]
//use test_case::test_case;
use std::rc::Rc;
use pretty_assertions::assert_eq;
use super::{tokenize, ParseResult, Parser};
use crate::{ast::*, tokenizing::Location};
fn rc(s: &str) -> Rc<String> {
Rc::new(s.to_owned())
}
fn bx<T>(item: T) -> Box<T> {
Box::new(item)
}
fn make_parser(input: &str) -> Parser {
let tokens: Vec<crate::tokenizing::Token> = tokenize(input);
let mut parser = super::Parser::new();
parser.add_new_tokens(tokens);
parser
}
fn parse(input: &str) -> ParseResult<AST> {
let mut parser = make_parser(input);
parser.parse()
}
fn stmt(kind: StatementKind) -> Statement {
Statement { location: Location::default(), id: ItemId::default(), kind }
}
fn decl(declaration: Declaration) -> Statement {
Statement {
location: Location::default(),
id: ItemId::default(),
kind: StatementKind::Declaration(declaration),
}
}
fn fn_decl(sig: Signature, stmts: Block) -> Statement {
Statement {
kind: StatementKind::Declaration(Declaration::FuncDecl(sig, stmts)),
location: Default::default(),
id: Default::default(),
}
}
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),* ) => {
{
let mut components = vec![];
$(
components.push(rc(stringify!($component)));
)*
QualifiedName { components, id: Default::default() }
}
};
}
fn int_anno() -> TypeIdentifier {
TypeIdentifier::Singleton(TypeSingletonName { name: rc("Int"), params: vec![] })
}
macro_rules! assert_ast {
($input:expr, $statements:expr) => {
let ast = parse($input).unwrap();
let expected = AST { id: Default::default(), statements: $statements.into() };
println!("Expected: {}", expected);
println!("Actual: {}", ast);
assert_eq!(ast, expected);
};
}
macro_rules! assert_fail {
($input:expr, $failure:expr) => {
let err = parse($input).unwrap_err();
assert_eq!(err.msg, $failure);
};
}
macro_rules! assert_expr {
($input:expr, $correct:expr) => {
let mut parser = make_parser($input);
assert_eq!(parser.expression().unwrap(), $correct);
};
}
macro_rules! assert_fail_expr {
($input:expr, $failure:expr) => {
let mut parser = make_parser($input);
let err = parser.expression().unwrap_err();
assert_eq!(err.msg, $failure);
};
}
#[test]
fn basic_literals() {
use ExpressionKind::*;
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)));
assert_expr!("0xf_f_", expr(NatLiteral(255)));
assert_expr!("false", expr(BoolLiteral(false)));
assert_expr!("true", expr(BoolLiteral(true)));
assert_expr!(r#""hello""#, expr(StringLiteral(rc("hello"))));
}
#[test]
fn binexps() {
use ExpressionKind::*;
use StatementKind::Expression;
assert_expr!("0xf_f_+1", binop("+", expr(NatLiteral(255)), expr(NatLiteral(1))));
assert_eq!(
parse("3; 4; 4.3").unwrap(),
AST {
id: Default::default(),
statements: vec![
stmt(Expression(expr(NatLiteral(3)))),
stmt(Expression(expr(NatLiteral(4)))),
stmt(Expression(expr(FloatLiteral(4.3)))),
]
.into()
}
);
assert_expr!(
"1 + 2 * 3",
binop("+", expr(NatLiteral(1)), binop("*", expr(NatLiteral(2)), expr(NatLiteral(3))))
);
assert_expr!(
"1 * 2 + 3",
binop("+", binop("*", expr(NatLiteral(1)), expr(NatLiteral(2))), expr(NatLiteral(3)))
);
assert_expr!("1 && 2", binop("&&", expr(NatLiteral(1)), expr(NatLiteral(2))));
assert_expr!(
"1 + 2 * 3 + 4",
binop(
"+",
binop("+", expr(NatLiteral(1)), binop("*", expr(NatLiteral(2)), expr(NatLiteral(3)))),
expr(NatLiteral(4))
)
);
assert_expr!(
"(1 + 2) * 3",
binop("*", binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))), expr(NatLiteral(3)))
);
assert_expr!(".1 + .2", binop("+", expr(FloatLiteral(0.1)), expr(FloatLiteral(0.2))));
assert_expr!("1 / 2.", binop("/", expr(NatLiteral(1)), expr(FloatLiteral(2.))));
}
#[test]
fn prefix_exps() {
use ExpressionKind::*;
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)))));
}
#[test]
fn operators() {
use ExpressionKind::*;
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))));
}
#[test]
fn accessors() {
use ExpressionKind::*;
assert_expr!("a.b", expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }));
assert_expr!(
"a.b.c",
expr(Access {
name: rc("c"),
expr: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }))
})
);
assert_expr!(
"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)))],
})
);
assert_expr!(
"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::*;
assert_expr!("()", expr(TupleLiteral(vec![])));
assert_expr!(
r#"("hella", 34)"#,
expr(TupleLiteral(vec![expr(StringLiteral(rc("hella"))), expr(NatLiteral(34))]))
);
assert_expr!(
r#"(1+2, "slough")"#,
expr(TupleLiteral(vec![
binop("+", expr(NatLiteral(1)), expr(NatLiteral(2))),
expr(StringLiteral(rc("slough"))),
]))
);
}
#[test]
fn identifiers() {
use ExpressionKind::*;
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!(
"thing::item::call()",
expr(Call { f: bx(expr(Value(qn!(thing, item, call)))), arguments: vec![] })
);
}
#[test]
fn named_struct() {
use ExpressionKind::*;
assert_expr!(
"Pandas { a: x + y }",
expr(NamedStruct {
name: qn!(Pandas),
fields: vec![(rc("a"), binop("+", expr(Value(qn!(x))), expr(Value(qn!(y)))))]
})
);
assert_expr!(
"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::*;
assert_expr!(
"a[b,c]",
expr(Index {
indexee: bx(expr(Value(qn!(a)))),
indexers: vec![expr(Value(qn!(b))), expr(Value(qn!(c)))]
})
);
assert_expr!(
"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)))] });
assert_expr!("a()[b]()[d]", d);
assert_fail_expr!("a[]", "Empty index expressions are not allowed");
}
#[test]
fn while_expression() {
use ExpressionKind::*;
assert_expr!("while { }", expr(WhileExpression { condition: None, body: Block::default() }));
assert_expr!(
"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::*;
assert_expr!(
"for { a <- garodzny::maybeValue } return 1",
expr(ForExpression {
enumerators: vec![Enumerator { id: rc("a"), generator: expr(Value(qn!(garodzny, maybeValue))) }],
body: bx(ForBody::MonadicReturn(expr(NatLiteral(1))))
})
);
assert_expr!(
"for n <- someRange { f(n); }",
expr(ForExpression {
enumerators: vec![Enumerator { id: rc("n"), generator: expr(Value(qn!(someRange))) }],
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::*;
assert_expr!(
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()
})
);
assert_expr!(
r#"\ (x: Int, y) { a;b;c;}"#,
expr(Lambda {
params: vec![
FormalParam { name: rc!(x), anno: Some(int_anno()), 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()
})
);
assert_expr!(
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)))],
})
);
assert_expr!(
r#"\(x: Int): String { "q" }"#,
expr(Lambda {
params: vec![FormalParam { name: rc!(x), anno: Some(int_anno()), default: None },],
type_anno: Some(TypeIdentifier::Singleton(TypeSingletonName {
name: rc("String"),
params: vec![]
})),
body: vec![stmt(StatementKind::Expression(expr(StringLiteral(rc("q"))))),].into()
})
);
}
#[test]
fn single_param_lambda() {
use ExpressionKind::*;
assert_expr!(
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()
})
);
assert_expr!(
r#"\x: Int { x + 10 }"#,
expr(Lambda {
params: vec![FormalParam { name: rc!(x), anno: Some(int_anno()), 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::*;
assert_ast! {
r#"fn wahoo() { let a = 10; \(x) { x + a } };
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() {
assert_fail!("module::item::call()", "Expected an identifier, got Colon");
}
#[test]
fn type_annotations() {
use ExpressionKind::*;
use TypeIdentifier::*;
assert_ast!(
"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![] })),
})]
);
assert_expr!(
"a: Int",
expr_anno(Value(qn!(a)), Singleton(TypeSingletonName { name: rc("Int"), params: vec![] }))
);
assert_expr!(
"a: Option<Int>",
expr_anno(
Value(qn!(a)),
Singleton(TypeSingletonName {
name: rc("Option"),
params: vec![Singleton(TypeSingletonName { name: rc("Int"), params: vec![] })]
})
)
);
assert_expr!(
"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![] })]
})
]
})
)
);
assert_expr!(
"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 declarations() {
use ExpressionKind::*;
assert_ast!(
"let q_q = Yolo::Swaggins",
vec![stmt(StatementKind::Declaration(Declaration::Binding {
name: rc("q_q"),
constant: true,
type_anno: None,
expr: expr(Value(qn!(Yolo, Swaggins)))
}))]
);
}
#[test]
fn bindings() {
use ExpressionKind::*;
assert_ast!(
"let mut a = 10",
vec![decl(Declaration::Binding {
name: rc("a"),
constant: false,
type_anno: None,
expr: expr(NatLiteral(10)),
})]
);
assert_ast!(
"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)))),
}))]
);
assert_ast!(
"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::*;
assert_ast!(
"fn oi()",
vec![stmt(StatementKind::Declaration(Declaration::FuncSig(Signature {
name: rc("oi"),
operator: false,
params: vec![],
type_anno: None
})))]
);
assert_ast!(
"oi()",
vec![stmt(StatementKind::Expression(expr(Call { f: bx(expr(Value(qn!(oi)))), arguments: vec![] })))]
);
assert_expr!(
"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)))),
]
})
);
assert_fail!("a(b,,c)", "Expected a literal expression, got Comma");
assert_ast!(
"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![] })),
})))]
);
}
#[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() {
assert_ast!(
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()
)]
);
}
}
#[test]
fn functions_with_default_args() {
use ExpressionKind::*;
assert_ast!(
"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(int_anno()), default: None },
FormalParam { name: rc("y"), anno: Some(int_anno()), default: Some(expr(NatLiteral(4))) },
],
},
vec![].into()
)]
);
}
#[test]
fn interface() {
let glue = TypeIdentifier::Singleton(TypeSingletonName { name: rc("Glue"), params: vec![] });
assert_ast!(
"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]
fn annotations() {
use ExpressionKind::*;
assert_ast! {
r#"
@test_annotation
fn some_function() {
}"#,
vec![decl(Declaration::Annotation {
name: rc("test_annotation"),
arguments: vec![]
}),
fn_decl(Signature { name: rc("some_function"), operator: false, params: vec![], type_anno: None },
vec![].into())
]
};
assert_ast! {
r#"
@test_annotation(some,value)
fn some_function() {
}"#,
vec![decl(Declaration::Annotation {
name: rc("test_annotation"),
arguments: vec![expr(Value(qn!(some))), expr(Value(qn!(value)))]
}),
fn_decl(Signature { name: rc("some_function"), operator: false, params: vec![], type_anno: None },
vec![].into())
]
};
}
#[test]
fn modules() {
assert_ast! {
r#"
module ephraim {
let mut a = 10
fn nah() { 33 }
}
"#,
vec![stmt(StatementKind::Module(ModuleSpecifier {
name: rc("ephraim"),
contents: vec![
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()
}))]
};
}
#[test]
fn imports() {
assert_ast! {
"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
}))]
};
assert_ast! {
"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")])
}))]
};
assert_ast! {
"import bespouri::{}",
vec![stmt(StatementKind::Import(ImportSpecifier {
id: Default::default(),
path_components: vec![rc("bespouri")],
imported_names: ImportedNames::List(vec![]),
}))]
};
assert_ast! {
"import bespouri::*",
vec![stmt(StatementKind::Import(ImportSpecifier {
id: Default::default(),
path_components: vec![rc("bespouri")],
imported_names: ImportedNames::All,
}))]
};
}

File diff suppressed because it is too large Load Diff