246 lines
8.0 KiB
Rust
246 lines
8.0 KiB
Rust
use std::vec;
|
|
|
|
use anyhow::bail;
|
|
use mclangc::{common::{Loc, loc::LocBox}, parser::{self, ast::{Ident, Keyword, Program, Punctuation, TokenType, statement::{Enum, Struct}, typ::Type}}, tokeniser::Token, validator::{self, predefined::{BuiltinType, get_builtin_from_name, load_builtin}}};
|
|
|
|
|
|
|
|
fn get_prog() -> Program {
|
|
let mut prog = Program::default();
|
|
load_builtin(&mut prog);
|
|
let loc = Loc::default();
|
|
prog.structs.insert(Ident::new("MyStruct"), LocBox::new(&loc, Struct {
|
|
name: Ident::new("MyStruct"),
|
|
fields: vec![
|
|
(Ident::new("foo"), LocBox::new(&loc, BuiltinType::usize())),
|
|
(Ident::new("bar"), LocBox::new(&loc, BuiltinType::bool())),
|
|
(Ident::new("baz"), LocBox::new(&loc, Type::Owned(Ident::new("str")).as_ref())),
|
|
]
|
|
}));
|
|
prog.enums.insert(Ident::new("MyEnum"), LocBox::new(&loc, Enum {
|
|
name: Ident::new("MyEnum"),
|
|
fields: vec![],
|
|
}));
|
|
prog.types.insert(Ident::new("MyType"), LocBox::new(&loc, Type::Owned(Ident::new("MyStruct"))));
|
|
prog.types.insert(Ident::new("MyType2"), LocBox::new(&loc, Type::Owned(Ident::new("MyType"))));
|
|
prog.types.insert(Ident::new("MyType3"), LocBox::new(&loc, Type::Owned(Ident::new("MyType2")).as_ref()));
|
|
prog.types.insert(Ident::new("MyTypeInf"), LocBox::new(&loc, Type::Owned(Ident::new("MyTypeInf"))));
|
|
prog.types.insert(Ident::new("MyTypeInfIndirect"), LocBox::new(&loc, Type::Owned(Ident::new("MyType4"))));
|
|
prog.types.insert(Ident::new("MyType4"), LocBox::new(&loc, Type::Owned(Ident::new("MyType5"))));
|
|
prog.types.insert(Ident::new("MyType5"), LocBox::new(&loc, Type::Owned(Ident::new("MyType4"))));
|
|
|
|
prog
|
|
}
|
|
|
|
#[test]
|
|
fn parse_type_alias_simple() {
|
|
let mut tokens = vec![
|
|
Token::new_test(TokenType::Ident(Ident::new("MyType")))
|
|
];
|
|
let ret = parser::typ::parse_type(&mut tokens);
|
|
let mut prog = get_prog();
|
|
let ret = validator::validate_type(&mut prog, &ret.unwrap());
|
|
assert!(ret.is_ok());
|
|
assert_eq!(ret.unwrap(), Type::Owned(Ident::new("MyStruct")))
|
|
}
|
|
|
|
#[test]
|
|
fn parse_type_alias_deep() {
|
|
let mut tokens = vec![
|
|
Token::new_test(TokenType::Ident(Ident::new("MyType3")))
|
|
];
|
|
let ret = parser::typ::parse_type(&mut tokens);
|
|
let mut prog = get_prog();
|
|
let ret = validator::validate_type(&mut prog, &ret.unwrap());
|
|
assert!(ret.is_ok());
|
|
assert_eq!(ret.unwrap(), Type::Owned(Ident::new("MyStruct")))
|
|
}
|
|
|
|
#[test]
|
|
fn parse_type_alias_recursive_simple() {
|
|
let mut tokens = vec![
|
|
Token::new_test(TokenType::Ident(Ident::new("MyTypeInf")))
|
|
];
|
|
let ret = parser::typ::parse_type(&mut tokens);
|
|
let mut prog = get_prog();
|
|
let ret = validator::validate_type(&mut prog, &ret.unwrap());
|
|
assert!(ret.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn parse_type_alias_recursive_indirect() {
|
|
let mut tokens = vec![
|
|
Token::new_test(TokenType::Ident(Ident::new("MyType4")))
|
|
];
|
|
let ret = parser::typ::parse_type(&mut tokens);
|
|
let mut prog = get_prog();
|
|
let ret = validator::validate_type(&mut prog, &ret.unwrap());
|
|
assert!(ret.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn parse_type_named_struct() {
|
|
let mut tokens = vec![
|
|
Token::new_test(TokenType::Ident(Ident::new("MyStruct")))
|
|
];
|
|
let ret = parser::typ::parse_type(&mut tokens);
|
|
assert!(ret.is_ok());
|
|
assert_eq!(ret.unwrap(), LocBox::new(&Loc::default(), Type::Owned(Ident::new("MyStruct"))))
|
|
}
|
|
|
|
#[test]
|
|
fn parse_type_named_enum() {
|
|
let mut tokens = vec![
|
|
Token::new_test(TokenType::Ident(Ident::new("MyEnum")))
|
|
];
|
|
let ret = parser::typ::parse_type(&mut tokens);
|
|
assert!(ret.is_ok());
|
|
assert_eq!(ret.unwrap(), LocBox::new(&Loc::default(), Type::Owned(Ident::new("MyEnum"))))
|
|
}
|
|
|
|
#[test]
|
|
fn parse_type_ref() {
|
|
let mut tokens = vec![
|
|
Token::new_test(TokenType::Punct(Punctuation::Ampersand)),
|
|
Token::new_test(TokenType::Ident(Ident::new("MyStruct")))
|
|
];
|
|
tokens.reverse();
|
|
let ret = parser::typ::parse_type(&mut tokens);
|
|
assert!(ret.is_ok());
|
|
assert_eq!(ret.unwrap(), LocBox::new(&Loc::default(), Type::Owned(Ident::new("MyStruct")).as_ref()))
|
|
}
|
|
|
|
#[test]
|
|
fn parse_type_ref2() {
|
|
let mut tokens = vec![
|
|
Token::new_test(TokenType::Punct(Punctuation::Ampersand)),
|
|
Token::new_test(TokenType::Punct(Punctuation::Ampersand)),
|
|
Token::new_test(TokenType::Ident(Ident::new("MyStruct")))
|
|
];
|
|
tokens.reverse();
|
|
let ret = parser::typ::parse_type(&mut tokens);
|
|
assert!(ret.is_ok());
|
|
assert_eq!(ret.unwrap(), LocBox::new(&Loc::default(), Type::Owned(Ident::new("MyStruct")).as_ref().as_ref()))
|
|
}
|
|
|
|
#[test]
|
|
fn parse_type_ref3() {
|
|
let mut tokens = vec![
|
|
Token::new_test(TokenType::Punct(Punctuation::Ampersand)),
|
|
Token::new_test(TokenType::Punct(Punctuation::Ampersand)),
|
|
Token::new_test(TokenType::Punct(Punctuation::Ampersand)),
|
|
Token::new_test(TokenType::Ident(Ident::new("MyStruct")))
|
|
];
|
|
tokens.reverse();
|
|
let ret = parser::typ::parse_type(&mut tokens);
|
|
assert!(ret.is_ok());
|
|
assert_eq!(ret.unwrap(), LocBox::new(&Loc::default(), Type::Owned(Ident::new("MyStruct")).as_ref().as_ref().as_ref()))
|
|
}
|
|
|
|
#[test]
|
|
fn parse_type_mut_ref() {
|
|
let mut tokens = vec![
|
|
Token::new_test(TokenType::Punct(Punctuation::Ampersand)),
|
|
Token::new_test(TokenType::Keyword(Keyword::Mut)),
|
|
Token::new_test(TokenType::Ident(Ident::new("MyStruct")))
|
|
];
|
|
tokens.reverse();
|
|
let ret = parser::typ::parse_type(&mut tokens);
|
|
assert!(ret.is_ok());
|
|
assert_eq!(ret.unwrap(), LocBox::new(&Loc::default(), Type::Owned(Ident::new("MyStruct")).as_ref_mut()))
|
|
}
|
|
|
|
#[test]
|
|
fn parse_type_mut_ref2() {
|
|
let mut tokens = vec![
|
|
Token::new_test(TokenType::Punct(Punctuation::Ampersand)),
|
|
Token::new_test(TokenType::Keyword(Keyword::Mut)),
|
|
Token::new_test(TokenType::Punct(Punctuation::Ampersand)),
|
|
Token::new_test(TokenType::Keyword(Keyword::Mut)),
|
|
Token::new_test(TokenType::Ident(Ident::new("MyStruct")))
|
|
];
|
|
tokens.reverse();
|
|
let ret = parser::typ::parse_type(&mut tokens);
|
|
assert!(ret.is_ok());
|
|
assert_eq!(ret.unwrap(), LocBox::new(&Loc::default(), Type::Owned(Ident::new("MyStruct")).as_ref_mut().as_ref_mut()))
|
|
}
|
|
|
|
#[test]
|
|
fn parse_type_mut_ref3() {
|
|
let mut tokens = vec![
|
|
Token::new_test(TokenType::Punct(Punctuation::Ampersand)),
|
|
Token::new_test(TokenType::Keyword(Keyword::Mut)),
|
|
Token::new_test(TokenType::Punct(Punctuation::Ampersand)),
|
|
Token::new_test(TokenType::Keyword(Keyword::Mut)),
|
|
Token::new_test(TokenType::Punct(Punctuation::Ampersand)),
|
|
Token::new_test(TokenType::Keyword(Keyword::Mut)),
|
|
Token::new_test(TokenType::Ident(Ident::new("MyStruct")))
|
|
];
|
|
tokens.reverse();
|
|
let ret = parser::typ::parse_type(&mut tokens);
|
|
assert!(ret.is_ok());
|
|
assert_eq!(ret.unwrap(), LocBox::new(&Loc::default(), Type::Owned(Ident::new("MyStruct")).as_ref_mut().as_ref_mut().as_ref_mut()))
|
|
}
|
|
|
|
fn test_builtin(s: &str) {
|
|
let mut tokens = vec![
|
|
Token::new_test(TokenType::Ident(Ident::new(s)))
|
|
];
|
|
let ret = parser::typ::parse_type(&mut tokens);
|
|
assert!(ret.is_ok());
|
|
assert_eq!(ret.unwrap(), LocBox::new(&Loc::default(), get_builtin_from_name(s).unwrap()))
|
|
}
|
|
|
|
#[test]
|
|
fn parse_type_builtin_usize() {
|
|
test_builtin("usize");
|
|
}
|
|
#[test]
|
|
fn parse_type_builtin_isize() {
|
|
test_builtin("isize");
|
|
}
|
|
#[test]
|
|
fn parse_type_builtin_u8() {
|
|
test_builtin("u8");
|
|
}
|
|
#[test]
|
|
fn parse_type_builtin_i8() {
|
|
test_builtin("i8");
|
|
}
|
|
#[test]
|
|
fn parse_type_builtin_u16() {
|
|
test_builtin("u16");
|
|
}
|
|
#[test]
|
|
fn parse_type_builtin_i16() {
|
|
test_builtin("i16");
|
|
}
|
|
#[test]
|
|
fn parse_type_builtin_u32() {
|
|
test_builtin("u32");
|
|
}
|
|
#[test]
|
|
fn parse_type_builtin_i32() {
|
|
test_builtin("i32");
|
|
}
|
|
#[test]
|
|
fn parse_type_builtin_u64() {
|
|
test_builtin("u64");
|
|
}
|
|
#[test]
|
|
fn parse_type_builtin_i64() {
|
|
test_builtin("i64");
|
|
}
|
|
#[test]
|
|
fn parse_type_builtin_void() {
|
|
test_builtin("void");
|
|
}
|
|
#[test]
|
|
fn parse_type_builtin_char() {
|
|
test_builtin("char");
|
|
}
|
|
#[test]
|
|
fn parse_type_builtin_bool() {
|
|
test_builtin("bool");
|
|
}
|