glowdust 0.0.1

A DBMS with a data model based on functions and pattern matching
Documentation
pub mod ast;
pub mod ast_walker;
pub mod lexer;
pub mod parse_state;
pub mod parser;
pub mod pointer;

use crate::compiler::parser::ast::{Span, DUMMY_SPAN};
use std::backtrace::Backtrace;
use std::error::Error;
use std::fmt;
use std::fmt::{Debug, Display};

#[derive(Debug, Clone)]
pub struct CompileError {
    pub message: String,
    pub span: Span,
    pub stack: Vec<String>,
}

impl CompileError {
    pub(crate) fn new(message: String, span: Span) -> CompileError {
        let mut stack = vec![];
        let bt = Backtrace::capture();
        let frames_iter = bt.frames();
        for (count, frame) in frames_iter.iter().enumerate() {
            if count < 4 {
                continue;
            }
            stack.push(format!("{:?}\n", frame));
            if count > 6 {
                break;
            }
        }
        return CompileError {
            message,
            span,
            stack,
        };
    }
}

impl Display for CompileError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.message)
    }
}

impl From<std::io::Error> for CompileError {
    fn from(err: std::io::Error) -> Self {
        CompileError::new(err.to_string(), DUMMY_SPAN)
    }
}

impl From<String> for CompileError {
    fn from(incoming: String) -> Self {
        CompileError::new(incoming, DUMMY_SPAN)
    }
}

impl Error for CompileError {}

#[cfg(test)]
pub(crate) mod tests {
    use crate::compiler::parser::lexer::TokenStream;
    use crate::compiler::parser::parse_state::ParseState;
    use crate::compiler::parser::parser::Parser;
    use crate::compiler::parser::CompileError;

    pub(crate) fn base_test(
        program: &str,
        should_compile_ok: bool,
    ) -> Result<ParseState, Vec<CompileError>> {
        let tokens = TokenStream::from(program);
        let mut parser = Parser::new(tokens);
        let mut result = ParseState::default();
        parser.parse(&mut result);

        for err in result.errors.iter() {
            println!("{}: {}", err.span, err.message);
        }

        assert_eq!(should_compile_ok, result.errors.is_empty());
        if !result.errors.is_empty() && should_compile_ok {
            Err(*result.errors)
        } else {
            Ok(result)
        }
        // for expression in &result.statements {
        //     println!("{:?}", expression);
        // }
    }
}