masmlint 0.1.1

A linter for Miden Assembly
Documentation
use std::sync::Arc;

use miden_assembly::{
    SourceId, SourceSpan, Span,
    ast::{Immediate, Instruction},
};

use crate::{EarlyContext, LintError, linter::EarlyLintPass};

pub struct BareAssert;

impl BareAssert {
    pub const NAME: &'static str = "bare_assert";
}

impl EarlyLintPass for BareAssert {
    fn lint_instruction(&mut self, early_ctx: &mut EarlyContext, instruction: &Span<Instruction>) {
        if let Some(assert_with_error) = match_assert_instruction(instruction) {
            early_ctx.push_error(LintError::BareAssert {
                span: instruction.span(),
                assert_with_error,
                source_file: early_ctx.source_file(),
            });
        }
    }
}

fn match_assert_instruction(instruction: &Span<Instruction>) -> Option<Instruction> {
    let example_msg = "helpful error message";
    let span = SourceSpan::at(SourceId::new(0), 0);
    let example_msg: Arc<str> = Arc::from(example_msg);
    let example_msg = Immediate::Value(Span::new(span, example_msg));

    match instruction.inner() {
        Instruction::Assert => Some(Instruction::AssertWithError(example_msg)),
        Instruction::AssertEq => Some(Instruction::AssertEqWithError(example_msg)),
        Instruction::AssertEqw => Some(Instruction::AssertEqwWithError(example_msg)),
        Instruction::Assertz => Some(Instruction::AssertzWithError(example_msg)),
        Instruction::U32Assert => Some(Instruction::U32AssertWithError(example_msg)),
        Instruction::U32Assert2 => Some(Instruction::U32Assert2WithError(example_msg)),
        Instruction::U32AssertW => Some(Instruction::U32AssertWWithError(example_msg)),
        Instruction::MTreeVerify => Some(Instruction::MTreeVerifyWithError(example_msg)),
        _ => None,
    }
}