use std::{ clone, fs, path::{Path, PathBuf}, sync::{Arc, Mutex, RwLock}, }; use dashmap::DashMap; use rowan::ast::{AstNode, AstPtr}; use crate::lst_parser::{ error::SyntaxError, grammar::source_file, input::Input, output::Output, syntax_kind, Parser, }; use super::{error::Error, modules::Module, nodes}; pub struct Loc { file: FileId, syntax: AstPtr, } #[derive(Clone)] pub struct Files(Arc); impl Files { pub fn new() -> Self { Self(Arc::new(FilesInner::new())) } pub fn add_and_parse(&self, file: &Path) -> Result<(FileId, Vec), std::io::Error> { self.0.add_and_parse(file) } pub fn get(&self, id: FileId) -> Arc { self.0.get(id) } } /// global file store /// contains all known files etc. struct FilesInner { paths: Mutex>, store: DashMap>, } impl FilesInner { fn new() -> Self { Self { paths: Mutex::new(Vec::new()), store: DashMap::new(), } } fn add_and_parse(&self, path: &Path) -> Result<(FileId, Vec), std::io::Error> { let (file, errors) = SourceFile::read_and_parse(&path)?; // add file to paths and unlock again let id = { let path = path.clone(); let mut paths = self.paths.lock().unwrap(); let r = paths.len(); paths.push(path.to_path_buf()); FileId(r) }; let _ = self.store.insert(path.to_path_buf(), Arc::new(file)); Ok(( id, errors .into_iter() .map(|e| Error::from_syntax(id, e)) .collect(), )) } fn get(&self, id: FileId) -> Arc { let path = { let paths = self.paths.lock().unwrap(); paths[id.0].clone() }; self.store.get(&path).unwrap().clone() } } pub struct SourceFile { pub lst: Mutex, root_module: Option>, } impl SourceFile { fn read_and_parse(path: &Path) -> Result<(Self, Vec), std::io::Error> { let source_text = fs::read_to_string(&path)?; let toks = syntax_kind::lex(&source_text); let input = Input::new(&toks); let mut parser = Parser::new(input); source_file(&mut parser); let events = parser.finish(); let out = Output::from_parser_output(toks, events); let lst = out.syntax(); Ok(( Self { lst: Mutex::new(nodes::Root::cast(lst).unwrap()), root_module: None, }, out.errors(), )) } } #[derive(Debug, Clone, Copy)] pub struct FileId(pub usize);