somni 0.2.0

Somni scripting language and VM
Documentation
use std::fmt::Debug;

use somni_expr::error::{ErrorWithLocation, MarkInSource};
use somni_parser::Location;

#[derive(Clone)]
pub struct CompileError<'s> {
    pub source: &'s str,
    pub location: Location,
    pub error: Box<str>,
}

impl<'s> CompileError<'s> {
    pub fn new(source: &'s str, error: impl ErrorWithLocation) -> Self {
        Self {
            source,
            location: error.location(),
            error: error.to_string().into_boxed_str(),
        }
    }
}

impl Debug for CompileError<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        std::fmt::Display::fmt(
            &MarkInSource(self.source, self.location, "Compile error", &self.error),
            f,
        )
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::strip_ansi;

    #[test]
    fn test_error() {
        let source = "1 + 2 * foo(3)";
        pretty_assertions::assert_eq!(
            r#"Compile error
 ---> at line 1 column 5
  |
1 | 1 + 2 * foo(3)
  |     ^ Syntax error"#,
            strip_ansi(format!(
                "{:?}",
                CompileError {
                    source,
                    location: Location { start: 4, end: 5 },
                    error: "Syntax error".to_string().into_boxed_str(),
                }
            ))
        );

        pretty_assertions::assert_eq!(
            r#"Compile error
 ---> at line 1 column 9
  |
1 | 1 + 2 * foo(3)
  |         ^^^^^^ Syntax error"#,
            strip_ansi(format!(
                "{:?}",
                CompileError {
                    source,
                    location: Location { start: 8, end: 14 },
                    error: "Syntax error".to_string().into_boxed_str(),
                }
            ))
        );
    }
}