M src/cache.rs => src/cache.rs +19 -13
@@ 136,9 136,8 @@ impl Cache {
pub fn fetch_global_resolved_name(&mut self, name: &FullName<PubIdent>) -> Result<Res> {
use ResolveErr::*;
- debug_assert!(name.len() >= 2);
let sname = name.clone().strip_locs();
- if sname.get(0).unwrap() == "prim" {
+ if sname.first() == "prim" {
if name.len() != 2 {
todo!() // Err
}
@@ 149,10 148,8 @@ impl Cache {
}
} else if let Some(&res) = self.resolved_names.get(&sname) {
Ok(res)
- } else if sname.get(0).unwrap() == "pkg" {
- todo!()
- } else if sname.get(0).unwrap() == "own" {
- let path = own_module_name_to_path(&self.root_dir, sname.rest().unwrap().iter().map(|s| s.as_str()));
+ } else if let "pkg" | "own" = sname.first().as_str() {
+ let path = self.module_name_to_path(&sname);
if path.exists() {
return Ok(Res::Module(self.gen_module_resolution(name.clone().strip_locs(), path)));
}
@@ 172,6 169,22 @@ impl Cache {
}
}
+ fn module_name_to_path(&self, mname: &FullName<String>) -> PathBuf {
+ if mname.first() == "pkg" {
+ todo!()
+ } else {
+ debug_assert!(mname.first() == "own");
+ let mut path = self.root_dir.to_path_buf();
+ if mname.len() == 1 {
+ path.push("lib.fm");
+ } else {
+ path.extend(mname.iter().skip(1));
+ path.set_extension("fm");
+ }
+ path
+ }
+ }
+
fn gen_module_resolution(&mut self, module_name: FullName<String>, path: PathBuf) -> ModuleId {
assert!(self.n_modules < u32::MAX);
let mid = ModuleId(self.n_modules);
@@ 240,10 253,3 @@ impl Cache {
self.file_paths.get(&file_id).expect("ice: we shouldn't have a file id without an associated file path")
}
}
-
-fn own_module_name_to_path<'a, I: IntoIterator<Item = &'a str>>(root: &Path, mname: I) -> PathBuf {
- let mut path = root.to_path_buf();
- path.extend(mname);
- path.set_extension("fm");
- path
-}
M src/main.rs => src/main.rs +36 -0
@@ 86,6 86,22 @@ mod test {
})
}
+ fn run_tmp_multi(app_module: &[&str], files: &[(&str, &str)]) -> std::result::Result<Operand, String> {
+ let dir = tempfile::tempdir().unwrap();
+ for (path, src) in files {
+ std::fs::write(dir.path().join(Path::new(path)), src).unwrap();
+ }
+ let mut cache = Cache::for_package_in(dir.path());
+ with_pretty_errors(&mut cache, |cache| {
+ let main_id = cache
+ .fetch_global_resolved_name(&name_in_cli(&[app_module, &["main"]].concat()))
+ .unwrap()
+ .as_def()
+ .unwrap();
+ cache.fetch_evaluated(main_id).cloned()
+ })
+ }
+
#[test]
fn test_main_literal() {
assert!(matches!(run_tmp("(def main 123.456)").unwrap(), Operand::Const(Const::F64(x)) if x == 123.456))
@@ 129,4 145,24 @@ mod test {
";
assert!(run_tmp(src).is_err())
}
+
+ #[test]
+ fn test_modules1() {
+ let main_src = "(def main (double.double.own. 21.0))";
+ let double_src = "(def double (of (Fun [F64] F64) (fun [x] (* x 2.0))))";
+ assert!(matches!(run_tmp_multi(&["own", "main"], &[
+ ("main.fm", main_src),
+ ("double.fm", double_src)
+ ]).unwrap(), Operand::Const(Const::F64(x)) if x == 42.0))
+ }
+
+ #[test]
+ fn test_modules2() {
+ let main_src = "(def main (double.own. 21.0))";
+ let lib_src = "(def double (of (Fun [F64] F64) (fun [x] (* x 2.0))))";
+ assert!(matches!(run_tmp_multi(&["own", "main"], &[
+ ("main.fm", main_src),
+ ("lib.fm", lib_src)
+ ]).unwrap(), Operand::Const(Const::F64(x)) if x == 42.0))
+ }
}
M src/name.rs => src/name.rs +13 -0
@@ 90,6 90,15 @@ impl<S> FullName<S> {
self.0.len()
}
+ pub fn init(mut self) -> Option<Self> {
+ self.0.pop();
+ if self.is_empty() {
+ None
+ } else {
+ Some(self)
+ }
+ }
+
pub fn rest(mut self) -> Option<Self> {
self.0.remove(0);
if self.is_empty() {
@@ 99,6 108,10 @@ impl<S> FullName<S> {
}
}
+ pub fn first(&self) -> &S {
+ &self.0[0]
+ }
+
pub fn last(&self) -> &S {
&self.0[self.0.len() - 1]
}