cl-parser: Forego RAII scopeguard finalization pattern in impl Fold for ModuleInliner
				
					
				
			We have an outer function *right there* to do cleanup for us.
This commit is contained in:
		| @@ -3,10 +3,7 @@ | ||||
| use crate::Parser; | ||||
| use cl_ast::{ast_visitor::Fold, *}; | ||||
| use cl_lexer::Lexer; | ||||
| use std::{ | ||||
|     ops::{Deref, DerefMut}, | ||||
|     path::{Path, PathBuf}, | ||||
| }; | ||||
| use std::path::{Path, PathBuf}; | ||||
|  | ||||
| type IoErrs = Vec<(PathBuf, std::io::Error)>; | ||||
| type ParseErrs = Vec<(PathBuf, crate::error::Error)>; | ||||
| @@ -26,77 +23,76 @@ impl ModuleInliner { | ||||
|             parse_errs: Default::default(), | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Returns true when the [ModuleInliner] has errors to report | ||||
|     pub fn has_errors(&self) -> bool { | ||||
|         !(self.io_errs.is_empty() && self.parse_errs.is_empty()) | ||||
|     } | ||||
|  | ||||
|     /// Returns the [IO Errors](IoErrs) and [parse Errors](ParseErrs) | ||||
|     pub fn into_errs(self) -> Option<(IoErrs, ParseErrs)> { | ||||
|         self.has_errors().then_some((self.io_errs, self.parse_errs)) | ||||
|     } | ||||
|  | ||||
|     /// Traverses a [File], attempting to inline all submodules. | ||||
|     /// | ||||
|     /// This is a simple wrapper around [ModuleInliner::fold_file()] and | ||||
|     /// [ModuleInliner::into_errs()] | ||||
|     pub fn inline(mut self, file: File) -> Result<File, (File, IoErrs, ParseErrs)> { | ||||
|         let file = self.fold_file(file); | ||||
|  | ||||
|         if self.io_errs.is_empty() && self.parse_errs.is_empty() { | ||||
|             Ok(file) | ||||
|         } else { | ||||
|             Err((file, self.io_errs, self.parse_errs)) | ||||
|         match self.into_errs() { | ||||
|             Some((io, parse)) => Err((file, io, parse)), | ||||
|             None => Ok(file), | ||||
|         } | ||||
|     } | ||||
|     /// Records an [I/O error](std::io::Error), and rebuilds the outline [Module] | ||||
|     fn io_oops(&mut self, name: Identifier, error: std::io::Error) -> Module { | ||||
|  | ||||
|     /// Records an [I/O error](std::io::Error) for later | ||||
|     fn handle_io_error(&mut self, error: std::io::Error) -> ModuleKind { | ||||
|         self.io_errs.push((self.path.clone(), error)); | ||||
|         Module { name, kind: ModuleKind::Outline } | ||||
|         ModuleKind::Outline | ||||
|     } | ||||
|     /// Records a [parse error](crate::error::Error), and rebuilds the outline [Module] | ||||
|     fn parse_oops(&mut self, name: Identifier, error: crate::error::Error) -> Module { | ||||
|  | ||||
|     /// Records a [parse error](crate::error::Error) for later | ||||
|     fn handle_parse_error(&mut self, error: crate::error::Error) -> ModuleKind { | ||||
|         self.parse_errs.push((self.path.clone(), error)); | ||||
|         Module { name, kind: ModuleKind::Outline } | ||||
|         ModuleKind::Outline | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Fold for ModuleInliner { | ||||
|     fn fold_module(&mut self, m: Module) -> cl_ast::Module { | ||||
|     /// Traverses down the module tree, entering ever nested directories | ||||
|     fn fold_module(&mut self, m: Module) -> Module { | ||||
|         let Module { name, kind } = m; | ||||
|         let mut inliner = PathMiser::new(self, &name.0); | ||||
|         self.path.push(&name.0); // cd ./name | ||||
|  | ||||
|         let kind = inliner.fold_module_kind(kind); | ||||
|         let kind = self.fold_module_kind(kind); | ||||
|  | ||||
|         let ModuleKind::Outline = kind else { | ||||
|             return Module { name, kind }; | ||||
|         }; | ||||
|         self.path.pop(); // cd .. | ||||
|         Module { name, kind } | ||||
|     } | ||||
|  | ||||
|         inliner.path.set_extension("cl"); | ||||
|         let file = match std::fs::read_to_string(&inliner.path) { | ||||
|             Err(e) => return inliner.io_oops(name, e), | ||||
|             Ok(s) => s, | ||||
|     /// Attempts to read and parse a file for every module in the tree | ||||
|     fn fold_module_kind(&mut self, m: ModuleKind) -> ModuleKind { | ||||
|         if let ModuleKind::Inline(f) = m { | ||||
|             return ModuleKind::Inline(self.fold_file(f)); | ||||
|         } | ||||
|         // cd path/mod.cl | ||||
|         self.path.set_extension("cl"); | ||||
|  | ||||
|         let file = match std::fs::read_to_string(&self.path) { | ||||
|             Err(error) => return self.handle_io_error(error), | ||||
|             Ok(file) => file, | ||||
|         }; | ||||
|  | ||||
|         let kind = match Parser::new(Lexer::new(&file)).file() { | ||||
|             Err(e) => return inliner.parse_oops(name, e), | ||||
|             Err(e) => return self.handle_parse_error(e), | ||||
|             Ok(file) => ModuleKind::Inline(file), | ||||
|         }; | ||||
|         // cd path/mod | ||||
|         self.path.set_extension(""); | ||||
|  | ||||
|         inliner.path.set_extension(""); | ||||
|         Module { name, kind: inliner.fold_module_kind(kind) } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// I am the [Path] miser. Whatever I touch turns to [Path] in my clutch. | ||||
| pub struct PathMiser<'mi> { | ||||
|     mi: &'mi mut ModuleInliner, | ||||
| } | ||||
| impl<'mi> PathMiser<'mi> { | ||||
|     pub fn new(mi: &'mi mut ModuleInliner, name: &str) -> Self { | ||||
|         mi.path.push(name); | ||||
|         Self { mi } | ||||
|     } | ||||
| } | ||||
| impl<'mi> Deref for PathMiser<'mi> { | ||||
|     type Target = ModuleInliner; | ||||
|     fn deref(&self) -> &Self::Target { | ||||
|         self.mi | ||||
|     } | ||||
| } | ||||
| impl<'mi> DerefMut for PathMiser<'mi> { | ||||
|     fn deref_mut(&mut self) -> &mut Self::Target { | ||||
|         self.mi | ||||
|     } | ||||
| } | ||||
| impl<'mi> Drop for PathMiser<'mi> { | ||||
|     fn drop(&mut self) { | ||||
|         self.mi.path.pop(); | ||||
|         // The newly loaded module may need further inlining | ||||
|         self.fold_module_kind(kind) | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user