use codespan_reporting::files::SimpleFiles; use codespan_reporting::term; use codespan_reporting::term::termcolor::{ColorChoice, StandardStream}; use deimos::ast::build::build_ast; use deimos::name_analysis::analyze_names; use deimos::name_analysis::symbol_table::SymbolTable; use deimos::parser::{DeimosParser, Rule}; use deimos::std_core::add_std_core_symbols; use pest::Parser; use std::collections::HashMap; use std::fmt::{Debug, Display, Formatter}; use std::path::PathBuf; use deimos::ast::node::CompilationUnit; struct ParseErrors { errors: Vec>, } impl Debug for ParseErrors { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { Display::fmt(self, f) } } impl Display for ParseErrors { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { writeln!(f, "There were errors during parsing.")?; for parse_error in &self.errors { writeln!(f, "{}", parse_error)?; } Ok(()) } } impl std::error::Error for ParseErrors {} pub fn name_analysis(paths: &[PathBuf]) -> Result, Box> { let mut paths_and_sources: HashMap = HashMap::new(); for path in paths { let src = std::fs::read_to_string(path).unwrap(); paths_and_sources.insert(path.display().to_string(), src); } let mut compilation_units = vec![]; let mut files: SimpleFiles<&str, &str> = SimpleFiles::new(); let mut parse_errors = vec![]; for (path, source) in &paths_and_sources { let parse_result = DeimosParser::parse(Rule::CompilationUnit, source); match parse_result { Ok(mut pairs) => { let file_id = files.add(path, source); let compilation_unit = build_ast(file_id, &mut pairs); compilation_units.push(compilation_unit); } Err(error) => { parse_errors.push(error); } } } if !parse_errors.is_empty() { return Err(Box::new(ParseErrors { errors: parse_errors, })); } let mut symbol_table = SymbolTable::new(); add_std_core_symbols(&mut symbol_table).expect("Failed to add std::core symbols."); let diagnostics = analyze_names(&mut compilation_units, &files, &mut symbol_table); if diagnostics.is_empty() { println!("Name analysis complete."); println!("{}", symbol_table); } else { let writer = StandardStream::stderr(ColorChoice::Always); let config = term::Config::default(); for diagnostic in diagnostics { term::emit(&mut writer.lock(), &config, &files, &diagnostic)?; } } Ok(compilation_units) }