Files
mclangc/tests/parser/typ.rs
2026-02-05 11:40:49 +02:00

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");
}