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 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
use crate::syntax::string_to_characters; use crate::*; use std::fmt; use std::io::{self, Read}; use std::path::PathBuf; pub struct Source { pub kind: SourceKind, pub uri: URI, pub code: String, } #[derive(Clone)] pub enum SourceKind { Module, REPLLine, } impl Source { pub fn new(kind: SourceKind, uri: URI, code: String) -> Arc<Source> { Arc::new(Source { kind, uri, code }) } pub fn main<S: AsRef<str>>(main_class: S) -> Arc<Source> { let main_class = main_class.as_ref(); let class_name = main_class.split("/").collect::<Vec<_>>().pop().unwrap(); Source::new( SourceKind::REPLLine, URI::Main, format!("import {}.\n\n{} run asString.", main_class, class_name), ) } pub fn file(path: PathBuf) -> io::Result<Arc<Source>> { let uri = URI::File(path.clone()); Self::file_with_uri(path, uri) } pub fn stdin() -> io::Result<Arc<Source>> { let mut code = String::new(); io::stdin().read_to_string(&mut code)?; Ok(Self::new(SourceKind::Module, URI::Stdin, code)) } pub fn files<S: AsRef<str>>(s: S) -> io::Result<Vec<Arc<Source>>> { Self::files_with_uri(s.as_ref(), |path| URI::File(path)) } fn files_with_uri<F: Fn(PathBuf) -> URI>(g: &str, f: F) -> io::Result<Vec<Arc<Source>>> { let mut sources = vec![]; match glob::glob(g) { Ok(paths) => { for path in paths { if let Ok(path) = path { let uri = f(path.clone()); sources.push(Self::file_with_uri(path, uri)?); } } } _ => (), } Ok(sources) } fn file_with_uri(path: PathBuf, uri: URI) -> io::Result<Arc<Source>> { let path = path.canonicalize()?; Ok(Self::new( SourceKind::Module, uri, std::fs::read_to_string(path)?, )) } pub fn stdlib() -> io::Result<Vec<Arc<Source>>> { Self::files_with_uri(sdk_glob(&["std", "**", "*.loa"]).as_ref(), |path| { URI::Stdlib(path) }) } pub fn len(&self) -> usize { string_to_characters(self.code.clone()).len() } #[cfg(test)] pub fn test(code: &str) -> Arc<Source> { Self::new(SourceKind::Module, URI::Test, code.into()) } #[cfg(test)] pub fn test_repl(code: &str) -> Arc<Source> { Self::new(SourceKind::REPLLine, URI::Test, code.into()) } } impl fmt::Display for Source { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.uri) } } impl fmt::Debug for Source { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Source({})", self.uri) } }