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, }, Lang, }; use super::{error::Error, modules::Module, nodes}; #[derive(Clone)] pub struct Loc> { file: FileId, syntax: AstPtr, } impl> Loc { pub fn new(node: N, file: FileId) -> Self { Self { file, syntax: AstPtr::new(&node), } } pub fn file(&self) -> FileId { self.file } pub fn syntax(&self) -> AstPtr { self.syntax.clone() } } /// global file store /// contains all known files etc. #[derive(Clone)] pub struct Files { paths: Arc>>, store: Arc>>, } impl Files { pub fn new() -> Self { Self { paths: Arc::new(Mutex::new(Vec::new())), store: Arc::new(DashMap::new()), } } pub 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(), )) } pub 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 fn get_path(&self, id: FileId) -> PathBuf { let paths = self.paths.lock().unwrap(); paths[id.0].clone() } pub fn path_store(&self) -> Arc>> { self.paths.clone() } } pub struct SourceFile { pub lst: RwLock, 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(); let (lst, errors) = out.dissolve(); Ok(( Self { lst: RwLock::new(lst), root_module: None, }, errors, )) } } #[derive(Debug, Clone, Copy)] pub struct FileId(pub usize);