luallaby 0.1.0

**Work in progress** A pure-Rust Lua interpreter/compiler
Documentation
use std::cmp::Ordering;
use std::fmt::{self, Write};
use std::rc::Rc;

use serde::{Deserialize, Serialize};

#[derive(Debug, Clone)]
pub enum Token {
    // Generic
    Ident(String),
    String(Rc<Vec<u8>>, StringType),
    Integer(i64, String),
    Float(f64, String),
    // Keywords
    And,
    Break,
    Do,
    Else,
    Elseif,
    End,
    False,
    For,
    Function,
    Goto,
    If,
    In,
    Local,
    Nil,
    Not,
    Or,
    Repeat,
    Return,
    Then,
    True,
    Until,
    While,
    // Delimiters
    Add,
    Sub,
    Mul,
    Div,
    Mod,
    Pow,
    Hash,
    Amp,
    Tilde,
    Bar,
    Shl,
    Shr,
    FlDiv,
    Eq,
    Neq,
    Leq,
    Geq,
    Lt,
    Gt,
    Is,
    ParO,
    ParC,
    CurlO,
    CurlC,
    SqrO,
    SqrC,
    Ass,
    Semi,
    Colon,
    Comma,
    Point,
    Conc,
    Dots,
}

impl fmt::Display for Token {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Token::Ident(ident) => f.write_str(ident),
            Token::String(str, typ) => match typ {
                StringType::Double => write!(f, "\"{}\"", String::from_utf8_lossy(str).as_ref()),
                StringType::Single => write!(f, "'{}'", String::from_utf8_lossy(str).as_ref()),
                StringType::Long(len) => {
                    write!(
                        f,
                        "[{1}[{}]{1}]",
                        String::from_utf8_lossy(str).as_ref(),
                        "=".repeat(*len)
                    )
                }
            },
            Token::Integer(_, orig) => f.write_str(orig),
            Token::Float(_, orig) => f.write_str(orig),
            Token::And => f.write_str("and"),
            Token::Break => f.write_str("break"),
            Token::Do => f.write_str("do"),
            Token::Else => f.write_str("else"),
            Token::Elseif => f.write_str("elseif"),
            Token::End => f.write_str("end"),
            Token::False => f.write_str("false"),
            Token::For => f.write_str("for"),
            Token::Function => f.write_str("function"),
            Token::Goto => f.write_str("goto"),
            Token::If => f.write_str("if"),
            Token::In => f.write_str("in"),
            Token::Local => f.write_str("local"),
            Token::Nil => f.write_str("nil"),
            Token::Not => f.write_str("not"),
            Token::Or => f.write_str("or"),
            Token::Repeat => f.write_str("repeat"),
            Token::Return => f.write_str("return"),
            Token::Then => f.write_str("then"),
            Token::True => f.write_str("true"),
            Token::Until => f.write_str("until"),
            Token::While => f.write_str("while"),
            Token::Add => f.write_char('+'),
            Token::Sub => f.write_char('-'),
            Token::Mul => f.write_char('*'),
            Token::Div => f.write_char('/'),
            Token::Mod => f.write_char('%'),
            Token::Pow => f.write_char('^'),
            Token::Hash => f.write_char('#'),
            Token::Amp => f.write_char('&'),
            Token::Tilde => f.write_char('~'),
            Token::Bar => f.write_char('|'),
            Token::Shl => f.write_str("<<"),
            Token::Shr => f.write_str(">>"),
            Token::FlDiv => f.write_str("//"),
            Token::Eq => f.write_str("=="),
            Token::Neq => f.write_str("~="),
            Token::Leq => f.write_str("<="),
            Token::Geq => f.write_str(">="),
            Token::Lt => f.write_char('<'),
            Token::Gt => f.write_char('>'),
            Token::Is => f.write_char('='),
            Token::ParO => f.write_char('('),
            Token::ParC => f.write_char(')'),
            Token::CurlO => f.write_char('{'),
            Token::CurlC => f.write_char('}'),
            Token::SqrO => f.write_char('['),
            Token::SqrC => f.write_char(']'),
            Token::Ass => f.write_str("::"),
            Token::Semi => f.write_char(';'),
            Token::Colon => f.write_char(':'),
            Token::Comma => f.write_char(','),
            Token::Point => f.write_char('.'),
            Token::Conc => f.write_str(".."),
            Token::Dots => f.write_str("..."),
        }
    }
}

#[derive(Clone, Debug)]
pub enum StringType {
    Single,
    Double,
    Long(usize),
}

pub struct Spanned<T> {
    pub(super) inner: T,
    pub(super) pos: Pos,
}

impl<T> Spanned<T> {
    pub fn inner(&self) -> &T {
        &self.inner
    }

    pub fn pos(&self) -> Pos {
        self.pos
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Pos(pub(super) i64, pub(super) i64);

impl Pos {
    pub fn line(&self) -> i64 {
        self.0
    }

    pub fn col(&self) -> i64 {
        self.1
    }
}

impl Default for Pos {
    fn default() -> Self {
        Self(-1, -1)
    }
}

impl Ord for Pos {
    fn cmp(&self, other: &Self) -> Ordering {
        self.0.cmp(&other.0).then(self.1.cmp(&other.1))
    }
}

impl PartialOrd for Pos {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl From<Spanned<Token>> for (Pos, Token) {
    fn from(value: Spanned<Token>) -> Self {
        (value.pos, value.inner)
    }
}

impl<'a> From<&'a Spanned<Token>> for (Pos, &'a Token) {
    fn from(value: &'a Spanned<Token>) -> Self {
        (value.pos, &value.inner)
    }
}