//! Тесты на отсутствие ошибок при парсинге.
use rasm_core::{
    lexer::Lexer,
    parser::{Parser, err::ParserError},
    src::SourceCode,
    str_pool::StrPool,
};

fn no_err(code: &str) -> Result<(), Vec<ParserError>> {
    let source = SourceCode::new(code.to_string());

    let mut str_pool = StrPool::from_source(&source);
    let mut lexer = Lexer::new(&mut str_pool, source);
    lexer.tokenize();

    assert!(lexer.errors.is_empty(), "{:?}", lexer.errors);

    let mut parser = Parser::new(&lexer.tokens, &mut str_pool);
    parser.parse();

    if !parser.errors.is_empty() {
        Err(parser.errors)
    } else {
        Ok(())
    }
}

#[test]
pub fn no_err_in_loop() {
    no_err(
        "
_start:
    mov rcx, 10

loop_start:
    dec rcx
    jnz loop_start

    xor rax, rax
    ret",
    )
    .unwrap()
}

#[test]
pub fn no_err_registers_and_sizes() {
    no_err(
        "
    mov al, 0xFF
    mov ax, 255
    mov eax, 1000
    mov r8, r9
    ",
    )
    .unwrap();
}

#[test]
pub fn no_err_multiple_labels() {
    no_err(
        "
label1:
label2:
label:
    nop
    jmp label1
    jmp label
    ",
    )
    .unwrap();
}

#[test]
pub fn no_err_memory_addressing() {
    no_err(
        "
    mov rax, [rbx]
    mov [rcx], rdx
    mov rsi, [rdi + rcx*8 + 16] ; Сложный адрес
    ",
    )
    .unwrap();
}

#[test]
pub fn no_err_all_instruction_types() {
    no_err(
        "
    nop                 ; 0 операндов
    push rax            ; 1 операнд
    mov rax, rbx        ; 2 операнда
    ",
    )
    .unwrap();
}
