From 5105ebf09cd319e7664bbc50b912a3d21837f6d4 Mon Sep 17 00:00:00 2001 From: Sofia R Date: Tue, 9 May 2023 15:06:52 -0300 Subject: [PATCH] feat: transformed into a comment --- crates/kind-cli/src/main.rs | 193 +++++++++++++----- crates/kind-driver/src/lib.rs | 2 + crates/kind-driver/src/resolution.rs | 45 ++-- crates/kind-pass/src/diagnostic.rs | 12 +- .../suite/issues/checker/ArityOnLet.golden | 3 +- 5 files changed, 183 insertions(+), 72 deletions(-) diff --git a/crates/kind-cli/src/main.rs b/crates/kind-cli/src/main.rs index 9467b76e..b780ddee 100644 --- a/crates/kind-cli/src/main.rs +++ b/crates/kind-cli/src/main.rs @@ -115,6 +115,10 @@ pub enum Command { #[clap(aliases = &["s"])] Show { file: String }, + /// Gets direct dependencies of a file + #[clap(aliases = &["gd"])] + GetDeps { file: String }, + /// Compiles a file to Kindelia (.kdl) #[clap(aliases = &["kdl"])] ToKDL { @@ -160,11 +164,21 @@ pub fn run_in_session( root: PathBuf, file: String, compiled: bool, + silent: bool, action: &mut dyn FnMut(&mut Session) -> anyhow::Result, ) -> anyhow::Result { let log = |session: &Session, report: &dyn Report| render_to_stderr(render_config, session, report); - driver::run_in_session(render_config, root, file, compiled, action, &log) + let sil = |_: &Session, _: &dyn Report| (); + + driver::run_in_session( + render_config, + root, + file, + compiled, + action, + if silent { &sil } else { &log }, + ) } pub fn run_cli(config: Cli) -> anyhow::Result<()> { @@ -182,7 +196,7 @@ pub fn run_cli(config: Cli) -> anyhow::Result<()> { config.hide_vals, mode, config.hide_deps, - config.get_deps + config.get_deps, ); let root = config.root.unwrap_or_else(|| PathBuf::from(".")); @@ -195,97 +209,172 @@ pub fn run_cli(config: Cli) -> anyhow::Result<()> { match config.command { Command::Check { file, coverage } => { - run_in_session(&render_config, root, file.clone(), false, &mut |session| { - let (_, rewrites) = driver::type_check_book( - session, - &PathBuf::from(file.clone()), - entrypoints.clone(), - config.tids, - coverage, - )?; + run_in_session( + &render_config, + root, + file.clone(), + false, + false, + &mut |session| { + let (_, rewrites) = driver::type_check_book( + session, + &PathBuf::from(file.clone()), + entrypoints.clone(), + config.tids, + coverage, + )?; - render_to_stderr(&render_config, session, &Log::Rewrites(rewrites)); + render_to_stderr(&render_config, session, &Log::Rewrites(rewrites)); - Ok(()) - })?; + Ok(()) + }, + )?; } Command::ToHVM { file } => { - let result = - run_in_session(&render_config, root, file.clone(), true, &mut |session| { + let result = run_in_session( + &render_config, + root, + file.clone(), + true, + false, + &mut |session| { let book = driver::erase_book( session, &PathBuf::from(file.clone()), entrypoints.clone(), )?; Ok(driver::compile_book_to_hvm(book, config.trace)) - })?; + }, + )?; println!("{}", result); } Command::Run { file } => { - let res = run_in_session(&render_config, root, file.clone(), true, &mut |session| { - let path = PathBuf::from(file.clone()); - let book = driver::erase_book(session, &path, entrypoints.clone())?; - driver::check_main_entry(session, &book)?; - let book = driver::compile_book_to_hvm(book, config.trace); - let (result, rewrites) = driver::execute_file(&book.to_string(), config.tids)?; + let res = run_in_session( + &render_config, + root, + file.clone(), + true, + false, + &mut |session| { + let path = PathBuf::from(file.clone()); + let book = driver::erase_book(session, &path, entrypoints.clone())?; + driver::check_main_entry(session, &book)?; + let book = driver::compile_book_to_hvm(book, config.trace); + let (result, rewrites) = driver::execute_file(&book.to_string(), config.tids)?; - render_to_stderr(&render_config, session, &Log::Rewrites(rewrites)); + render_to_stderr(&render_config, session, &Log::Rewrites(rewrites)); - Ok(result) - })?; + Ok(result) + }, + )?; println!("{}", res); } Command::Show { file } => { - run_in_session(&render_config, root, file.clone(), true, &mut |session| { - driver::to_book(session, &PathBuf::from(file.clone())) - }) + run_in_session( + &render_config, + root, + file.clone(), + true, + false, + &mut |session| driver::to_book(session, &PathBuf::from(file.clone())), + ) .map(|res| { print!("{}", res); res })?; } Command::ToKindCore { file } => { - let res = run_in_session(&render_config, root, file.clone(), true, &mut |session| { - driver::desugar_book(session, &PathBuf::from(file.clone())) - })?; + let res = run_in_session( + &render_config, + root, + file.clone(), + true, + false, + &mut |session| driver::desugar_book(session, &PathBuf::from(file.clone())), + )?; print!("{}", res); } Command::Erase { file } => { - let res = run_in_session(&render_config, root, file.clone(), true, &mut |session| { - driver::erase_book(session, &PathBuf::from(file.clone()), entrypoints.clone()) - })?; + let res = run_in_session( + &render_config, + root, + file.clone(), + true, + false, + &mut |session| { + driver::erase_book(session, &PathBuf::from(file.clone()), entrypoints.clone()) + }, + )?; print!("{}", res); } Command::GenChecker { file, coverage } => { - let res = run_in_session(&render_config, root, file.clone(), true, &mut |session| { - driver::check_erasure_book(session, &PathBuf::from(file.clone())) - })?; + let res = run_in_session( + &render_config, + root, + file.clone(), + true, + false, + &mut |session| driver::check_erasure_book(session, &PathBuf::from(file.clone())), + )?; print!("{}", driver::generate_checker(&res, coverage)); } Command::Eval { file } => { - let res = run_in_session(&render_config, root, file.clone(), true, &mut |session| { - let book = driver::desugar_book(session, &PathBuf::from(file.clone()))?; - driver::check_main_desugared_entry(session, &book)?; - let (res, rewrites) = driver::eval_in_checker(&book); + let res = run_in_session( + &render_config, + root, + file.clone(), + true, + false, + &mut |session| { + let book = driver::desugar_book(session, &PathBuf::from(file.clone()))?; + driver::check_main_desugared_entry(session, &book)?; + let (res, rewrites) = driver::eval_in_checker(&book); - render_to_stderr(&render_config, session, &Log::Rewrites(rewrites)); + render_to_stderr(&render_config, session, &Log::Rewrites(rewrites)); - Ok(res) - })?; + Ok(res) + }, + )?; println!("{}", res); } Command::ToKDL { file, namespace } => { - let res = run_in_session(&render_config, root, file.clone(), true, &mut |session| { - driver::compile_book_to_kdl( - &PathBuf::from(file.clone()), - session, - &namespace.clone().unwrap_or("".to_string()), - entrypoints.clone(), - ) - })?; + let res = run_in_session( + &render_config, + root, + file.clone(), + true, + false, + &mut |session| { + driver::compile_book_to_kdl( + &PathBuf::from(file.clone()), + session, + &namespace.clone().unwrap_or("".to_string()), + entrypoints.clone(), + ) + }, + )?; println!("{}", res); } + Command::GetDeps { file } => { + let res = run_in_session( + &render_config, + root, + file.clone(), + true, + true, + &mut |session| { + Ok(driver::get_unbound_variables( + session, + &PathBuf::from(file.clone()), + )) + }, + )?; + + if let Some(res) = res { + println!("{}", res.join(" ")); + } + } } Ok(()) diff --git a/crates/kind-driver/src/lib.rs b/crates/kind-driver/src/lib.rs index deb8d2b6..cfb281a4 100644 --- a/crates/kind-driver/src/lib.rs +++ b/crates/kind-driver/src/lib.rs @@ -20,6 +20,8 @@ pub mod diagnostic; pub mod resolution; pub mod session; +pub use resolution::get_unbound_variables; + impl FileCache for Session { fn fetch(&self, ctx: SyntaxCtxIndex) -> Option<(PathBuf, &String)> { let path = self.loaded_paths[ctx.0].as_ref().to_owned(); diff --git a/crates/kind-driver/src/resolution.rs b/crates/kind-driver/src/resolution.rs index 2b2c1d1b..5206b8f4 100644 --- a/crates/kind-driver/src/resolution.rs +++ b/crates/kind-driver/src/resolution.rs @@ -191,6 +191,21 @@ fn parse_and_store_book_by_identifier( } } +fn read_file(session: &mut Session, path: &Path) -> Option { + match fs::read_to_string(path) { + Ok(res) => Some(res), + Err(_) => { + session + .diagnostic_sender + .send(Box::new(DriverDiagnostic::CannotFindFile( + path.to_str().unwrap().to_string(), + ))) + .unwrap(); + None + } + } +} + fn parse_and_store_book_by_path(session: &mut Session, path: &PathBuf, book: &mut Book, immediate: bool) -> bool { if !path.exists() { let err = Box::new(DriverDiagnostic::CannotFindFile( @@ -207,18 +222,7 @@ fn parse_and_store_book_by_path(session: &mut Session, path: &PathBuf, book: &mu return false; } - let input = match fs::read_to_string(path) { - Ok(res) => res, - Err(_) => { - session - .diagnostic_sender - .send(Box::new(DriverDiagnostic::CannotFindFile( - path.to_str().unwrap().to_string(), - ))) - .unwrap(); - return true; - } - }; + let Some(input) = read_file(session, path) else { return true }; let ctx_id = session.book_counter; session.add_path(Rc::new(fs::canonicalize(path).unwrap()), input.clone()); @@ -250,6 +254,23 @@ fn parse_and_store_book_by_path(session: &mut Session, path: &PathBuf, book: &mu failed } +pub fn get_unbound_variables(session: &mut Session, path: &Path) -> Option> { + let tx = session.diagnostic_sender.clone(); + + let Some(input) = read_file(session, path) else { return None }; + + let (mut module, _) = kind_parser::parse_book(tx.clone(), 0, &input); + + expand_uses(&mut module, tx.clone()); + expand_module(tx.clone(), &mut module); + + let mut state = UnboundCollector::new(tx.clone(), false); + state.visit_module(&mut module); + + Some(state.unbound_top_level.keys().cloned().collect()) +} + + fn unbound_variable(session: &mut Session, book: &Book, idents: &[Ident]) { let mut similar_names = book .names diff --git a/crates/kind-pass/src/diagnostic.rs b/crates/kind-pass/src/diagnostic.rs index acfd6d80..67e68dde 100644 --- a/crates/kind-pass/src/diagnostic.rs +++ b/crates/kind-pass/src/diagnostic.rs @@ -322,20 +322,20 @@ impl Diagnostic for PassDiagnostic { DiagnosticFrame { code: 210, severity: Severity::Error, - title: "Incorrect arity.".to_string(), - subtitles: vec![], - hints: vec![if *expected == 0 { + title: if *expected == 0 { format!("This function expects no arguments but got {}", got.len()) } else if *hidden == 0 { - format!("This function expects {} arguments but got {}", expected, got.len()) + format!("This function expects exactly {} arguments but got {}", expected, got.len()) } else { format!( - "This function expects {} arguments or {} (without hidden ones) but got {}.", + "This function expects exactly {} arguments or {} (without hidden ones) but got {}.", expected, expected - hidden, got.len() ) - }], + }, + subtitles: vec![], + hints: vec![], positions, } } diff --git a/crates/kind-tests/suite/issues/checker/ArityOnLet.golden b/crates/kind-tests/suite/issues/checker/ArityOnLet.golden index 43448da8..8a58644c 100644 --- a/crates/kind-tests/suite/issues/checker/ArityOnLet.golden +++ b/crates/kind-tests/suite/issues/checker/ArityOnLet.golden @@ -1,4 +1,4 @@ - ERROR Incorrect arity. + ERROR This function expects exactly 1 arguments but got 0 /--[suite/issues/checker/ArityOnLet.kind2:6:13] | @@ -8,5 +8,4 @@ | \This function requires a fixed number of arguments 7 | 2 - Hint: This function expects 1 arguments but got 0