~jojo/effem

6a4251c503359d69a13fa332c46a2978982b06e3 — JoJo 1 year, 30 days ago fe0b767
Add & fix test for using modules in code. Resolve own. to lib.fm

This now works

src/lib.fm:
  (def double (of (Fun [F64] F64) (fun [x] (* x 2.0))))

src/main.fm
  (def main (double.own. 21.0))

eval main.main.own. => 42
3 files changed, 68 insertions(+), 13 deletions(-)

M src/cache.rs
M src/main.rs
M src/name.rs
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]
    }