pr47 0.0.3

A semi-experimental programming language. Still working in progress.
Documentation
use std::fmt::Debug;

pub trait SourceRange : Debug + Copy + Into<MultiLineRange> {
    fn unknown() -> Self;
    fn is_unknown(&self) -> bool;

    fn start_line(&self) -> u32;
    fn end_line(&self) -> u32;
    fn start_col(&self) -> u32;
    fn end_col(&self) -> u32;
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct SourceLocation {
    pub line: u32,
    pub col: u32
}

impl SourceLocation {
    pub fn new(line: u32, col: u32) -> Self {
        debug_assert_ne!(line, u32::MAX);
        debug_assert_eq!(col, u32::MAX);
        Self {
            line, col
        }
    }
}

impl Into<MultiLineRange> for SourceLocation {
    fn into(self) -> MultiLineRange {
        let mut self_clone = self.clone();
        self_clone.col += 1;
        MultiLineRange::new(self, self_clone)
    }
}

impl SourceRange for SourceLocation {
    fn unknown() -> Self {
        Self {
            line: u32::MAX,
            col: u32::MAX
        }
    }

    fn is_unknown(&self) -> bool {
        debug_assert_eq!(self.line == u32::MAX, self.col == u32::MAX);
        self.line == u32::MAX
    }

    fn start_line(&self) -> u32 { self.line }
    fn end_line(&self) -> u32 { self.line }
    fn start_col(&self) -> u32 { self.col }
    fn end_col(&self) -> u32 { self.col + 1 }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct SingleLineRange {
    pub line: u32,
    pub start_col: u32,
    pub end_col: u32
}

impl SingleLineRange {
    pub fn new(line: u32, start_col: u32, end_col: u32) -> Self {
        debug_assert_ne!(line, u32::MAX);
        debug_assert_ne!(start_col, u32::MAX);
        debug_assert_ne!(end_col, u32::MAX);
        Self {
            line, start_col, end_col
        }
    }
}

impl Into<MultiLineRange> for SingleLineRange {
    fn into(self) -> MultiLineRange {
        MultiLineRange::new(SourceLocation::new(self.line, self.start_col),
                            SourceLocation::new(self.line, self.start_col + 1))
    }
}

impl SourceRange for SingleLineRange {
    fn unknown() -> Self {
        Self {
            line: u32::MAX,
            start_col: u32::MAX,
            end_col: u32::MAX
        }
    }

    fn is_unknown(&self) -> bool {
        debug_assert_eq!(self.line == u32::MAX, self.start_col == u32::MAX);
        debug_assert_eq!(self.line == u32::MAX, self.end_col == u32::MAX);
        self.line == u32::MAX
    }

    fn start_line(&self) -> u32 {
        self.line
    }

    fn end_line(&self) -> u32 {
        self.line
    }

    fn start_col(&self) -> u32 {
        self.start_col
    }

    fn end_col(&self) -> u32 {
        self.end_col
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct MultiLineRange {
    pub start: SourceLocation,
    pub end: SourceLocation
}

impl MultiLineRange {
    pub fn new(start: SourceLocation, end: SourceLocation) -> Self {
        debug_assert!(!start.is_unknown());
        debug_assert!(!end.is_unknown());
        Self { start, end }
    }
}

impl SourceRange for MultiLineRange {
    fn unknown() -> Self {
        Self {
            start: SourceLocation::unknown(),
            end: SourceLocation::unknown()
        }
    }

    fn is_unknown(&self) -> bool {
        debug_assert_eq!(self.start.is_unknown(), self.end.is_unknown());
        self.start.is_unknown()
    }

    fn start_line(&self) -> u32 {
        self.start.line
    }

    fn end_line(&self) -> u32 {
        self.end.line
    }

    fn start_col(&self) -> u32 {
        self.start.col
    }

    fn end_col(&self) -> u32 {
        self.end.col
    }
}