1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
use crate::{ exp, parse, stdlib, CallSnapshot, Environment, Exception, ExceptionValue as EV, Expression, }; use relative_path::RelativePath; use std::env; use std::fs; use std::path::PathBuf; use crate::Locker; pub fn resolve_resource( path: &str, snapshot: Locker<CallSnapshot>, via: &Expression, env: Locker<Environment>, ) -> Result<Expression, Exception> { let content = match path.starts_with('@') { true => match stdlib::get_std_resource(path) { Some(val) => val, None => exp!( EV::InvalidIncludePath(String::from(path)), snapshot, format!("`{}` is not in the standard library", path) ), }, false => { let source_path_opt = match via.source() { Some(source) => match source.location() { Some(location) => Some(location), None => None, }, None => None, }; let working_dir = match env::current_dir() { Ok(dir) => dir, Err(_) => exp!( EV::InvalidIncludePath(String::from(path)), snapshot, "could not establish working directory (the environment is unknown)" .to_string() ), }; let relative_dir = match source_path_opt { Some(source_path) => match fs::metadata(&source_path) { Ok(metadata) => match metadata.is_dir() { true => PathBuf::from(source_path), false => match PathBuf::from(source_path).parent() { Some(parent) => PathBuf::from(parent), None => working_dir, }, }, Err(_) => working_dir, }, None => working_dir, }; let relative_dir_composed = match RelativePath::from_path(&path) { Ok(relative) => relative, Err(err) => exp!( EV::InvalidIncludePath(String::from(path)), snapshot, format!( "could not understand include path ({}; all includes must be relative)", err ) ), }; match fs::read_to_string(&relative_dir_composed.to_path(relative_dir)) { Ok(value) => value, Err(val) => exp!( EV::InvalidIncludePath(path.to_string()), snapshot, format!("unable to read file ({})", val) ), } } }; let parsed = parse(&content, &path.to_string())?; let mut return_val = Expression::nil(); for exp in parsed { return_val = exp.eval(CallSnapshot::new(&exp, &snapshot)?, env.clone())?; } Ok(return_val) }