From afae1d3b4a912f2433db0b80ad96713393aba2b8 Mon Sep 17 00:00:00 2001 From: Felipe g Date: Mon, 7 Nov 2022 10:15:28 -0300 Subject: [PATCH 1/9] fix: bullet unicode now is on the chars struct --- src/kind-cli/src/main.rs | 8 ++------ src/kind-report/src/lib.rs | 13 ++++++++++++- src/kind-report/src/report.rs | 6 +++--- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/kind-cli/src/main.rs b/src/kind-cli/src/main.rs index ea51c5c4..0f6b8738 100644 --- a/src/kind-cli/src/main.rs +++ b/src/kind-cli/src/main.rs @@ -3,7 +3,7 @@ use std::time::Instant; use std::{fmt, io}; use clap::{Parser, Subcommand}; -use kind_driver::resolution::{compile_book, type_check_book}; +use kind_driver::resolution::{type_check_book}; use kind_driver::{session::Session}; use kind_report::data::{Diagnostic, DiagnosticFrame, Log}; use kind_report::report::{FileCache, Report}; @@ -115,11 +115,7 @@ fn main() { kind_report::check_if_colors_are_supported(config.no_color); - let render_config = if config.ascii { - RenderConfig::ascii(2) - } else { - RenderConfig::unicode(2) - }; + let render_config = kind_report::check_if_utf8_is_supported(config.no_color, 2); match config.command { Command::Check { file } => { diff --git a/src/kind-report/src/lib.rs b/src/kind-report/src/lib.rs index 26189bd7..6271f9e1 100644 --- a/src/kind-report/src/lib.rs +++ b/src/kind-report/src/lib.rs @@ -14,6 +14,7 @@ pub struct Chars { pub bxline: char, pub brline: char, pub ylline: char, + pub bullet: char, } impl Chars { @@ -26,6 +27,7 @@ impl Chars { bxline: '┬', brline: '┌', ylline: '├', + bullet: '•', } } pub fn ascii() -> &'static Chars { @@ -37,6 +39,7 @@ impl Chars { bxline: 'v', brline: '/', ylline: '-', + bullet: '*', } } } @@ -63,7 +66,15 @@ impl<'a> RenderConfig<'a> { } pub fn check_if_colors_are_supported(disable: bool) { - if cfg!(windows) && !Paint::enable_windows_ascii() || disable { + if disable || (cfg!(windows) && !Paint::enable_windows_ascii()) { Paint::disable(); } } + +pub fn check_if_utf8_is_supported<'a>(disable: bool, indent: usize) -> RenderConfig<'a> { + if disable || (cfg!(windows) && !Paint::enable_windows_ascii()) { + RenderConfig::ascii(indent) + } else { + RenderConfig::unicode(indent) + } +} \ No newline at end of file diff --git a/src/kind-report/src/report.rs b/src/kind-report/src/report.rs index cf8a798c..3537f6bb 100644 --- a/src/kind-report/src/report.rs +++ b/src/kind-report/src/report.rs @@ -409,7 +409,7 @@ impl<'a> Report for Diagnostic<'a> { match subtitle { Subtitle::Normal(color, phr) => { let colorizer = get_colorizer(color); - writeln!(fmt, "{:>5} {} {}", "", colorizer("•"), Paint::new(phr))?; + writeln!(fmt, "{:>5} {} {}", "", colorizer(config.chars.bullet), Paint::new(phr))?; } Subtitle::Bold(color, phr) => { let colorizer = get_colorizer(color); @@ -417,13 +417,13 @@ impl<'a> Report for Diagnostic<'a> { fmt, "{:>5} {} {}", "", - colorizer("•"), + colorizer(config.chars.bullet), Paint::new(phr).bold() )?; } Subtitle::Phrase(color, words) => { let colorizer = get_colorizer(color); - write!(fmt, "{:>5} {} ", "", colorizer("•"))?; + write!(fmt, "{:>5} {} ", "", colorizer(config.chars.bullet))?; for word in words { match word { Word::Normal(str) => write!(fmt, "{} ", Paint::new(str))?, From 47c99d01e3c783f89b034265a7083abc5371e8d6 Mon Sep 17 00:00:00 2001 From: Felipe g Date: Mon, 7 Nov 2022 10:55:39 -0300 Subject: [PATCH 2/9] feat: added all of the commands that we can use right now --- src/kind-checker/src/lib.rs | 25 +++++- src/kind-cli/src/main.rs | 130 +++++++++++++++++++++--------- src/kind-driver/Cargo.toml | 1 + src/kind-driver/src/lib.rs | 66 ++++++++++++++- src/kind-driver/src/resolution.rs | 38 +-------- src/kind-tree/src/concrete/mod.rs | 17 +++- 6 files changed, 195 insertions(+), 82 deletions(-) diff --git a/src/kind-checker/src/lib.rs b/src/kind-checker/src/lib.rs index 523496f6..8a92d010 100644 --- a/src/kind-checker/src/lib.rs +++ b/src/kind-checker/src/lib.rs @@ -4,6 +4,7 @@ pub mod report; use std::sync::mpsc::Sender; +use hvm::Term; use kind_report::data::DiagnosticFrame; use kind_tree::desugared::Book; @@ -13,11 +14,19 @@ const CHECKER_HVM: &str = include_str!("checker.hvm"); /// Type checks a dessugared book. It spawns an HVM instance in order /// to run a compiled version of the book -pub fn type_check(book: &Book, tx: Sender) -> bool { +pub fn gen_checker(book: &Book) -> String { let base_check_code = compiler::codegen_book(book); let mut check_code = CHECKER_HVM.to_string(); check_code.push_str(&base_check_code.to_string()); + check_code +} + +/// Type checks a dessugared book. It spawns an HVM instance in order +/// to run a compiled version of the book +pub fn type_check(book: &Book, tx: Sender) -> bool { + let check_code = gen_checker(book); + let mut runtime = hvm::Runtime::from_code(&check_code).unwrap(); let main = runtime.alloc_code("Kind.API.check_all").unwrap(); runtime.run_io(main); @@ -34,3 +43,17 @@ pub fn type_check(book: &Book, tx: Sender) -> bool { succeeded } + +/// Type checks a dessugared book. It spawns an HVM instance in order +/// to run a compiled version of the book +pub fn eval_api(book: &Book) -> Box { + let check_code = gen_checker(book); + + let mut runtime = hvm::Runtime::from_code(&check_code).unwrap(); + let main = runtime.alloc_code("Kind.API.eval_main").unwrap(); + runtime.run_io(main); + runtime.normalize(main); + let term = runtime.readback(main); + + term +} diff --git a/src/kind-cli/src/main.rs b/src/kind-cli/src/main.rs index 0f6b8738..8b48bdfa 100644 --- a/src/kind-cli/src/main.rs +++ b/src/kind-cli/src/main.rs @@ -3,12 +3,14 @@ use std::time::Instant; use std::{fmt, io}; use clap::{Parser, Subcommand}; -use kind_driver::resolution::{type_check_book}; -use kind_driver::{session::Session}; +use driver::resolution; +use kind_driver::session::Session; use kind_report::data::{Diagnostic, DiagnosticFrame, Log}; use kind_report::report::{FileCache, Report}; use kind_report::RenderConfig; +use kind_driver as driver; + #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] #[clap(propagate_version = true)] @@ -110,52 +112,102 @@ where .unwrap(); } +pub fn compile_in_session( + render_config: RenderConfig, + root: PathBuf, + file: String, + fun: &mut dyn FnMut(&mut Session) -> Option, +) -> Option { + let (rx, tx) = std::sync::mpsc::channel(); + + let mut session = Session::new(root, rx); + + eprintln!(); + + render_to_stderr( + &render_config, + &session, + &Log::Checking(format!("the file '{}'", file)), + ); + + let start = Instant::now(); + + let res = fun(&mut session); + + let diagnostics = tx.try_iter().collect::>(); + + if diagnostics.is_empty() { + render_to_stderr(&render_config, &session, &Log::Checked(start.elapsed())); + } else { + render_to_stderr(&render_config, &session, &Log::Failed(start.elapsed())); + eprintln!(); + for diagnostic in diagnostics { + let diagnostic: Diagnostic = (&diagnostic).into(); + render_to_stderr(&render_config, &session, &diagnostic) + } + } + + eprintln!(); + + res +} + fn main() { let config = Cli::parse(); kind_report::check_if_colors_are_supported(config.no_color); - let render_config = kind_report::check_if_utf8_is_supported(config.no_color, 2); + let render_config = kind_report::check_if_utf8_is_supported(config.ascii, 2); + let root = PathBuf::from("."); match config.command { Command::Check { file } => { - let (rx, tx) = std::sync::mpsc::channel(); - - let mut session = Session::new(PathBuf::from("."), rx); - - eprintln!(); - - render_to_stderr( - &render_config, - &session, - &Log::Checking(format!("the file '{}'", file)), - ); - - let start = Instant::now(); - - type_check_book(&mut session, &PathBuf::from(file)); - - let diagnostics = tx.try_iter().collect::>(); - - if diagnostics.is_empty() { - render_to_stderr(&render_config, &session, &Log::Checked(start.elapsed())); - } else { - render_to_stderr(&render_config, &session, &Log::Failed(start.elapsed())); - eprintln!(); - for diagnostic in diagnostics { - let diagnostic: Diagnostic = (&diagnostic).into(); - render_to_stderr(&render_config, &session, &diagnostic) - } - } - eprintln!(); + compile_in_session(render_config, root, file.clone(), &mut |session| { + driver::type_check_book(session, &PathBuf::from(file.clone())) + }); } - Command::Eval { file } => todo!(), - Command::Run { file } => todo!(), - Command::GenChecker { file } => todo!(), - Command::Show { file } => todo!(), - Command::ToKDL { file, namespace } => todo!(), - Command::ToHVM { file } => todo!(), - Command::Watch { file } => todo!(), + Command::ToHVM { file } => { + compile_in_session(render_config, root, file.clone(), &mut |session| { + driver::compile_book_to_hvm(session, &PathBuf::from(file.clone())) + }).and_then(|res| { + println!("{}", res); + Some(res) + }); + } + Command::Run { file } => { + compile_in_session(render_config, root, file.clone(), &mut |session| { + driver::compile_book_to_hvm(session, &PathBuf::from(file.clone())) + }).and_then(|res| { + println!("{}", driver::execute_file(&res)); + Some(res) + }); + } + Command::Eval { file } => { + compile_in_session(render_config, root, file.clone(), &mut |session| { + driver::erase_book(session, &PathBuf::from(file.clone())) + }).and_then(|res| { + println!("{}", driver::eval_in_checker(&res)); + Some(res) + }); + } + Command::Show { file } => { + compile_in_session(render_config, root, file.clone(), &mut |session| { + driver::to_book(session, &PathBuf::from(file.clone())) + }).and_then(|res| { + print!("{}", res); + Some(res) + }); + } + Command::GenChecker { file } => { + compile_in_session(render_config, root, file.clone(), &mut |session| { + driver::erase_book(session, &PathBuf::from(file.clone())) + }).and_then(|res| { + print!("{}", driver::generate_checker(&res)); + Some(res) + }); + } + Command::ToKDL { file: _, namespace: _ } => todo!(), + Command::Watch { file: _ } => todo!(), Command::Repl => todo!(), } } diff --git a/src/kind-driver/Cargo.toml b/src/kind-driver/Cargo.toml index 689e1c4c..2199f891 100644 --- a/src/kind-driver/Cargo.toml +++ b/src/kind-driver/Cargo.toml @@ -14,6 +14,7 @@ kind-checker = { path = "../kind-checker" } kind-pass = { path = "../kind-pass" } kind-target-hvm = { path = "../kind-target-hvm" } +hvm = "0.1.81" strsim = "0.10.0" fxhash = "0.2.1" dashmap = "5.4.0" diff --git a/src/kind-driver/src/lib.rs b/src/kind-driver/src/lib.rs index 7dfc4fff..2d86e177 100644 --- a/src/kind-driver/src/lib.rs +++ b/src/kind-driver/src/lib.rs @@ -1,8 +1,12 @@ +use kind_pass::{expand, desugar, erasure}; use kind_report::report::FileCache; use kind_span::SyntaxCtxIndex; +use kind_tree::{desugared, backend, concrete}; use session::Session; -use std::path::PathBuf; +use std::{path::PathBuf, collections::HashSet}; + +use kind_checker as checker; pub mod errors; pub mod resolution; @@ -14,3 +18,63 @@ impl FileCache for Session { Some((path, &self.loaded_sources[ctx.0])) } } + +pub fn type_check_book(session: &mut Session, path: &PathBuf) -> Option { + let concrete_book = to_book(session, path)?; + let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?; + let succeeded = checker::type_check(&desugared_book, session.diagnostic_sender.clone()); + + if !succeeded { + return None; + } + + let erased = erasure::erase_book( + &desugared_book, + session.diagnostic_sender.clone(), + HashSet::from_iter(vec!["Main".to_string()]), + )?; + + Some(erased) +} + +pub fn to_book(session: &mut Session, path: &PathBuf) -> Option { + let mut concrete_book = resolution::parse_and_store_book(session, path)?; + + expand::expand_book(&mut concrete_book); + + Some(concrete_book) +} + +pub fn erase_book(session: &mut Session, path: &PathBuf) -> Option { + let concrete_book = to_book(session, path)?; + let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?; + erasure::erase_book( + &desugared_book, + session.diagnostic_sender.clone(), + HashSet::from_iter(vec!["Main".to_string()]), + ) +} + +pub fn compile_book_to_hvm(session: &mut Session, path: &PathBuf) -> Option { + erase_book(session, path).map(kind_target_hvm::compile_book) +} + +pub fn execute_file(file: &backend::File) -> Box { + // TODO: Change to from_file when hvm support it + let mut runtime = hvm::Runtime::from_code(&file.to_string()).unwrap(); + let main = runtime.alloc_code("Main").unwrap(); + runtime.run_io(main); + runtime.normalize(main); + let term = runtime.readback(main); + term +} + +pub fn eval_in_checker(book: &desugared::Book) -> Box { + // TODO: Change to from_file when hvm support it + checker::eval_api(book) +} + +pub fn generate_checker(book: &desugared::Book) -> String { + // TODO: Change to from_file when hvm support it + checker::gen_checker(book) +} \ No newline at end of file diff --git a/src/kind-driver/src/resolution.rs b/src/kind-driver/src/resolution.rs index 12af6709..4d23cf17 100644 --- a/src/kind-driver/src/resolution.rs +++ b/src/kind-driver/src/resolution.rs @@ -3,8 +3,6 @@ //! it returns a desugared book of all of the //! depedencies. -use kind_pass::erasure::{self}; -use kind_tree::desugared; use std::collections::HashSet; use std::fs; use std::path::{Path, PathBuf}; @@ -12,7 +10,6 @@ use std::rc::Rc; use strsim::jaro; use kind_pass::unbound::{self}; -use kind_pass::{desugar, expand}; use kind_report::data::DiagnosticFrame; use kind_tree::concrete::{Book, Module, TopLevel}; use kind_tree::symbol::{Ident, QualifiedIdent}; @@ -234,37 +231,4 @@ pub fn parse_and_store_book(session: &mut Session, path: &PathBuf) -> Option Option { - let mut concrete_book = parse_and_store_book(session, path)?; - - expand::expand_book(&mut concrete_book); - - let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?; - - let succeeded = kind_checker::type_check(&desugared_book, session.diagnostic_sender.clone()); - - if !succeeded { - return None; - } - - let erased = erasure::erase_book( - &desugared_book, - session.diagnostic_sender.clone(), - HashSet::from_iter(vec!["Main".to_string()]), - )?; - - Some(erased) -} - -pub fn compile_book(session: &mut Session, path: &PathBuf) -> Option<()> { - let book = type_check_book(session, path); - match book { - None => None, - Some(book) => { - println!("{}", kind_target_hvm::compile_book(book)); - Some(()) - } - } -} +} \ No newline at end of file diff --git a/src/kind-tree/src/concrete/mod.rs b/src/kind-tree/src/concrete/mod.rs index abcc17eb..14a65c1b 100644 --- a/src/kind-tree/src/concrete/mod.rs +++ b/src/kind-tree/src/concrete/mod.rs @@ -275,7 +275,7 @@ impl Display for TopLevel { } writeln!(f, "}}\n") } - TopLevel::Entry(entr) => writeln!(f, "{}\n", entr), + TopLevel::Entry(entr) => writeln!(f, "{}", entr), } } } @@ -283,7 +283,16 @@ impl Display for TopLevel { impl Display for Module { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { for entr in &self.entries { - writeln!(f, "{}", entr)?; + write!(f, "{}", entr)?; + } + Ok(()) + } +} + +impl Display for Book { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + for (_, entr) in &self.entries { + write!(f, "{}", entr)?; } Ok(()) } @@ -320,10 +329,10 @@ impl Display for Entry { write!(f, " {}", arg)?; } - write!(f, " : {}", &self.typ)?; + write!(f, " : {}\n", &self.typ)?; for rule in &self.rules { - write!(f, "\n{}", rule)? + write!(f, "{}\n", rule)? } Ok(()) From 670e67b05ce567ba6368c7bdf8b948135729c671 Mon Sep 17 00:00:00 2001 From: Felipe g Date: Mon, 7 Nov 2022 22:47:18 -0300 Subject: [PATCH 3/9] fix: fixes on qualified idents --- src/kind-checker/src/report.rs | 13 +++--- src/kind-cli/src/main.rs | 1 - src/kind-parser/src/expr.rs | 5 +- src/kind-parser/src/lexer/mod.rs | 3 +- src/kind-parser/src/lexer/tokens.rs | 3 +- src/kind-parser/src/top_level/mod.rs | 2 +- src/kind-pass/src/desugar/expr.rs | 10 ++-- src/kind-pass/src/desugar/top_level.rs | 4 +- src/kind-pass/src/expand/mod.rs | 10 +++- src/kind-pass/src/unbound/mod.rs | 65 +++++++++++++++----------- src/kind-tree/src/desugared/mod.rs | 2 + src/kind-tree/src/symbol.rs | 28 +++++++---- 12 files changed, 87 insertions(+), 59 deletions(-) diff --git a/src/kind-checker/src/report.rs b/src/kind-checker/src/report.rs index 43313220..822491b5 100644 --- a/src/kind-checker/src/report.rs +++ b/src/kind-checker/src/report.rs @@ -6,6 +6,11 @@ use kind_tree::{desugared, Operator}; use crate::errors::TypeError; use desugared::Expr; +type Entry = (String, Box, Vec>); + +#[derive(Debug)] +pub struct Context(pub Vec); + macro_rules! match_opt { ($expr:expr, $pat:pat => $end:expr) => { match $expr { @@ -15,11 +20,6 @@ macro_rules! match_opt { }; } -type Entry = (String, Box, Vec>); - -#[derive(Debug)] -pub struct Context(pub Vec); - fn parse_orig(term: &Term) -> Result { match_opt!(term, Term::Num { numb } => EncodedSpan(*numb).to_range()) } @@ -58,7 +58,8 @@ fn parse_name(term: &Term) -> Result { } fn parse_qualified(term: &Term) -> Result { - todo!() + let name = match_opt!(*term, Term::Num { numb } => Ident::decode(numb))?; + Ok(QualifiedIdent::new_static(&name, None, Range::ghost_range())) } fn parse_expr(term: &Term) -> Result, String> { diff --git a/src/kind-cli/src/main.rs b/src/kind-cli/src/main.rs index 8b48bdfa..aa21e763 100644 --- a/src/kind-cli/src/main.rs +++ b/src/kind-cli/src/main.rs @@ -3,7 +3,6 @@ use std::time::Instant; use std::{fmt, io}; use clap::{Parser, Subcommand}; -use driver::resolution; use kind_driver::session::Session; use kind_report::data::{Diagnostic, DiagnosticFrame, Log}; use kind_report::report::{FileCache, Report}; diff --git a/src/kind-parser/src/expr.rs b/src/kind-parser/src/expr.rs index 3e1be172..15c07b02 100644 --- a/src/kind-parser/src/expr.rs +++ b/src/kind-parser/src/expr.rs @@ -126,9 +126,8 @@ impl<'a> Parser<'a> { pub fn parse_upper_id(&mut self) -> Result { let range = self.range(); - let (start, end) = - eat_single!(self, Token::UpperId(start, end) => (start.clone(), end.clone()))?; - let ident = QualifiedIdent::new_static(start.clone(), end.clone(), range); + let (start, end) = eat_single!(self, Token::UpperId(start, end) => (start.clone(), end.clone()))?; + let ident = QualifiedIdent::new_static(start.as_str(), end.clone(), range); Ok(ident) } diff --git a/src/kind-parser/src/lexer/mod.rs b/src/kind-parser/src/lexer/mod.rs index 1c21a735..7f216a47 100644 --- a/src/kind-parser/src/lexer/mod.rs +++ b/src/kind-parser/src/lexer/mod.rs @@ -57,7 +57,8 @@ impl<'a> Lexer<'a> { "else" => Token::Else, "match" => Token::Match, "let" => Token::Let, - "open" => Token::Open, + "use" => Token::Use, + "as" => Token::As, "return" => Token::Return, "type" => Token::Type, "record" => Token::Record, diff --git a/src/kind-parser/src/lexer/tokens.rs b/src/kind-parser/src/lexer/tokens.rs index afdd192d..b48cbc61 100644 --- a/src/kind-parser/src/lexer/tokens.rs +++ b/src/kind-parser/src/lexer/tokens.rs @@ -34,10 +34,11 @@ pub enum Token { Ask, Return, Let, - Open, Type, Record, Constructor, + Use, + As, // Literals Char(char), diff --git a/src/kind-parser/src/top_level/mod.rs b/src/kind-parser/src/top_level/mod.rs index 6401b05b..7eab60df 100644 --- a/src/kind-parser/src/top_level/mod.rs +++ b/src/kind-parser/src/top_level/mod.rs @@ -81,7 +81,7 @@ impl<'a> Parser<'a> { let start = self.range(); let ident; if let Token::UpperId(name_id, ext) = self.get() { - let qual = QualifiedIdent::new_static(name_id.clone(), ext.clone(), start); + let qual = QualifiedIdent::new_static(name_id.as_str(), ext.clone(), start); if qual.to_string() == name { ident = self.parse_upper_id()?; } else { diff --git a/src/kind-pass/src/desugar/expr.rs b/src/kind-pass/src/desugar/expr.rs index ae36b206..19a10538 100644 --- a/src/kind-pass/src/desugar/expr.rs +++ b/src/kind-pass/src/desugar/expr.rs @@ -131,7 +131,7 @@ impl<'a> DesugarState<'a> { typ: &expr::Expr, body: &expr::Expr, ) -> Box { - let sigma = QualifiedIdent::new_static("Sigma".to_string(), None, range); + let sigma = QualifiedIdent::new_static("Sigma", None, range); let entry = self.old_book.entries.get(sigma.to_string().as_str()); if entry.is_none() { @@ -157,7 +157,7 @@ impl<'a> DesugarState<'a> { range: Range, expr: &[expr::Expr], ) -> Box { - let list_ident = QualifiedIdent::new_static("List".to_string(), None, range); + let list_ident = QualifiedIdent::new_static("List", None, range); let cons_ident = list_ident.add_segment("cons"); let nil_ident = list_ident.add_segment("nil"); @@ -186,8 +186,7 @@ impl<'a> DesugarState<'a> { if_: &expr::Expr, else_: &expr::Expr, ) -> Box { - let bool_ident = - QualifiedIdent::new_static("Bool".to_string(), Some("if".to_string()), range); + let bool_ident = QualifiedIdent::new_sugared("Bool", "if", range); let bool_if = self.old_book.entries.get(bool_ident.to_string().as_str()); @@ -211,8 +210,7 @@ impl<'a> DesugarState<'a> { fst: &expr::Expr, snd: &expr::Expr, ) -> Box { - let sigma_new = - QualifiedIdent::new_static("Sigma".to_string(), Some("new".to_string()), range); + let sigma_new = QualifiedIdent::new_sugared("Sigma", "new", range); let entry = self.old_book.entries.get(sigma_new.to_string().as_str()); diff --git a/src/kind-pass/src/desugar/top_level.rs b/src/kind-pass/src/desugar/top_level.rs index 5ef5f847..d1932a84 100644 --- a/src/kind-pass/src/desugar/top_level.rs +++ b/src/kind-pass/src/desugar/top_level.rs @@ -188,7 +188,7 @@ impl<'a> DesugarState<'a> { snd: &concrete::pat::Pat, ) -> Box { let sigma_new = - QualifiedIdent::new_static("Sigma".to_string(), Some("new".to_string()), range); + QualifiedIdent::new_static("Sigma", Some("new".to_string()), range); let entry = self.old_book.entries.get(sigma_new.to_string().as_str()); if entry.is_none() { @@ -206,7 +206,7 @@ impl<'a> DesugarState<'a> { range: Range, expr: &[concrete::pat::Pat], ) -> Box { - let list_ident = QualifiedIdent::new_static("List".to_string(), None, range); + let list_ident = QualifiedIdent::new_static("List", None, range); let cons_ident = list_ident.add_segment("cons"); let nil_ident = list_ident.add_segment("nil"); diff --git a/src/kind-pass/src/expand/mod.rs b/src/kind-pass/src/expand/mod.rs index 87da1136..5005a8b8 100644 --- a/src/kind-pass/src/expand/mod.rs +++ b/src/kind-pass/src/expand/mod.rs @@ -1,7 +1,15 @@ +/// Expands identifiers sum type and record definitions + use std::collections::HashMap; use kind_derive::matching::derive_match; -use kind_tree::concrete::{Book, TopLevel}; +use kind_tree::concrete::{Book, TopLevel, visitor::Visitor}; + +pub struct Expand; + +impl Visitor for Expand { + +} pub fn expand_book(book: &mut Book) { let mut entries = HashMap::new(); diff --git a/src/kind-pass/src/unbound/mod.rs b/src/kind-pass/src/unbound/mod.rs index d26b1242..cff80d72 100644 --- a/src/kind-pass/src/unbound/mod.rs +++ b/src/kind-pass/src/unbound/mod.rs @@ -84,6 +84,16 @@ impl Visitor for UnboundCollector { } } + fn visit_qualified_ident(&mut self, ident: &mut QualifiedIdent) { + if !self.context_vars.iter().any(|x| x.1 == ident.to_string()) { + let entry = self + .unbound_top_level + .entry(ident.to_string()) + .or_insert_with(|| Vec::new()); + entry.push(ident.clone()); + } + } + fn visit_pat_ident(&mut self, ident: &mut PatIdent) { if let Some(fst) = self .context_vars @@ -117,6 +127,9 @@ impl Visitor for UnboundCollector { } fn visit_entry(&mut self, entry: &mut Entry) { + self.context_vars + .push((entry.name.range, entry.name.to_string())); + let vars = self.context_vars.clone(); for arg in entry.args.iter_mut() { @@ -176,10 +189,7 @@ impl Visitor for UnboundCollector { self.context_vars = inside_vars; } - TopLevel::Entry(entr) => { - self.context_vars.push((entr.range, entr.to_string())); - self.visit_entry(entr) - } + TopLevel::Entry(entr) => self.visit_entry(entr), } } @@ -203,7 +213,7 @@ impl Visitor for UnboundCollector { fn visit_destruct(&mut self, destruct: &mut Destruct) { match destruct { Destruct::Destruct(range, ty, bindings, _) => { - self.visit_ident(&mut Ident::new_by_sugar(&format!("{}.open", ty), *range)); + self.visit_qualified_ident(QualifiedIdent::add_segment(ty, "open").to_sugar()); self.visit_range(range); self.visit_qualified_ident(ty); for bind in bindings { @@ -304,15 +314,7 @@ impl Visitor for UnboundCollector { fn visit_expr(&mut self, expr: &mut Expr) { match &mut expr.data { ExprKind::Var(ident) => self.visit_ident(ident), - ExprKind::Constr(ident) => { - if !self.context_vars.iter().any(|x| x.1 == ident.to_string()) { - let entry = self - .unbound_top_level - .entry(ident.to_string()) - .or_insert_with(|| Vec::new()); - entry.push(ident.clone()); - } - } + ExprKind::Constr(ident) => self.visit_qualified_ident(ident), ExprKind::All(None, typ, body) => { self.visit_expr(typ); self.visit_expr(body); @@ -353,18 +355,23 @@ impl Visitor for UnboundCollector { self.context_vars = vars; } ExprKind::Sigma(None, typ, body) => { - self.visit_ident(&mut Ident::new_by_sugar("Sigma", expr.range)); + self.visit_qualified_ident( + &mut QualifiedIdent::new_static("Sigma", None, expr.range).to_sugar(), + ); self.visit_expr(typ); self.visit_expr(body); } ExprKind::Sigma(Some(ident), typ, body) => { - self.visit_ident(&mut Ident::new_by_sugar("Sigma", expr.range)); + self.visit_qualified_ident( + &mut QualifiedIdent::new_static("Sigma", None, expr.range).to_sugar(), + ); self.visit_expr(typ); self.context_vars.push((ident.range, ident.to_string())); self.visit_expr(body); self.context_vars.pop(); } ExprKind::Match(matcher) => { + self.visit_qualified_ident(&mut matcher.typ.add_segment("match").to_sugar()); self.visit_ident(&mut Ident::new_by_sugar( &format!("{}.match", matcher.typ.to_string().as_str()), expr.range, @@ -386,30 +393,32 @@ impl Visitor for UnboundCollector { } ExprKind::Hole => {} ExprKind::Do(typ, sttm) => { - self.visit_ident(&mut Ident::new_by_sugar( - &format!("{}.pure", typ), - expr.range, - )); - self.visit_ident(&mut Ident::new_by_sugar( - &format!("{}.bind", typ), - expr.range, - )); + self.visit_qualified_ident(&mut typ.add_segment("pure").to_sugar()); + self.visit_qualified_ident(&mut typ.add_segment("bind").to_sugar()); self.visit_sttm(sttm) } ExprKind::If(cond, if_, else_) => { - self.visit_ident(&mut Ident::new_by_sugar("Bool.if", expr.range)); + self.visit_qualified_ident(&mut QualifiedIdent::new_sugared( + "Bool", "if", expr.range, + )); self.visit_expr(cond); self.visit_expr(if_); self.visit_expr(else_); } ExprKind::Pair(l, r) => { - self.visit_ident(&mut Ident::new_by_sugar("Pair.new", expr.range)); + self.visit_qualified_ident(&mut QualifiedIdent::new_sugared( + "Pair", "new", expr.range, + )); self.visit_expr(l); self.visit_expr(r); } ExprKind::List(spine) => { - self.visit_ident(&mut Ident::new_by_sugar("List.nil", expr.range)); - self.visit_ident(&mut Ident::new_by_sugar("List.cons", expr.range)); + self.visit_qualified_ident(&mut QualifiedIdent::new_sugared( + "List", "nil", expr.range, + )); + self.visit_qualified_ident(&mut QualifiedIdent::new_sugared( + "List", "cons", expr.range, + )); visit_vec!(spine.iter_mut(), arg => self.visit_expr(arg)); } } diff --git a/src/kind-tree/src/desugared/mod.rs b/src/kind-tree/src/desugared/mod.rs index f90387fd..82d2d0c3 100644 --- a/src/kind-tree/src/desugared/mod.rs +++ b/src/kind-tree/src/desugared/mod.rs @@ -3,6 +3,7 @@ use std::fmt::{Display, Error, Formatter}; +use fxhash::FxHashMap; use kind_span::{Range, Span}; use linked_hash_map::LinkedHashMap; @@ -253,6 +254,7 @@ pub struct Entry { #[derive(Clone, Debug, Default)] pub struct Book { pub entrs: LinkedHashMap>, + pub names: FxHashMap, pub holes: u64, } diff --git a/src/kind-tree/src/symbol.rs b/src/kind-tree/src/symbol.rs index e101ee01..27dfe2ec 100644 --- a/src/kind-tree/src/symbol.rs +++ b/src/kind-tree/src/symbol.rs @@ -50,27 +50,37 @@ impl QualifiedIdent { } } - pub fn new_static(root: String, aux: Option, range: Range) -> QualifiedIdent { + pub fn new_static(root: &str, aux: Option, range: Range) -> QualifiedIdent { QualifiedIdent { - root: Symbol(root), + root: Symbol(root.to_string()), aux: aux.map(Symbol), range, used_by_sugar: false, } } - pub fn add_segment(&self, extension: &str) -> QualifiedIdent { - let aux = match self.aux.clone() { - Some(res) => Symbol(format!("{}.{}", res.0, extension)), - None => Symbol(extension.to_string()), - }; + pub fn new_sugared(root: &str, aux: &str, range: Range) -> QualifiedIdent { QualifiedIdent { - root: self.root.clone(), - aux: Some(aux), + root: Symbol(root.to_string()), + aux: Some(Symbol(aux.to_string())), + range, + used_by_sugar: true, + } + } + + pub fn add_segment(&self, extension: &str) -> QualifiedIdent { + QualifiedIdent { + root: Symbol(format!("{}.{}", self.root.0, extension)), + aux: self.aux.clone(), range: self.range.clone(), used_by_sugar: self.used_by_sugar, } } + + pub fn to_sugar(&mut self) -> &mut QualifiedIdent { + self.used_by_sugar = true; + self + } } impl Ident { From b70793cfabab816c576971cc3782741233228cae Mon Sep 17 00:00:00 2001 From: Felipe g Date: Tue, 8 Nov 2022 11:47:51 -0300 Subject: [PATCH 4/9] feat: added small syntatic changes --- src/kind-cli/src/main.rs | 4 +- src/kind-derive/src/matching.rs | 10 +- src/kind-driver/src/resolution.rs | 52 +++++---- src/kind-parser/Cargo.toml | 4 +- src/kind-parser/src/errors.rs | 30 +++++ src/kind-parser/src/expr.rs | 68 ++++++++---- src/kind-parser/src/lexer/literals.rs | 8 +- src/kind-parser/src/top_level/mod.rs | 148 ++++++++++++++++++++----- src/kind-pass/src/desugar/app.rs | 9 +- src/kind-pass/src/desugar/expr.rs | 3 +- src/kind-pass/src/desugar/top_level.rs | 1 + src/kind-pass/src/errors.rs | 67 ++++++++--- src/kind-pass/src/expand/mod.rs | 15 +-- src/kind-pass/src/expand/uses.rs | 51 +++++++++ src/kind-pass/src/unbound/mod.rs | 5 +- src/kind-report/src/report.rs | 2 +- src/kind-tree/src/concrete/expr.rs | 9 +- src/kind-tree/src/concrete/mod.rs | 3 +- src/kind-tree/src/concrete/visitor.rs | 7 +- src/kind-tree/src/symbol.rs | 4 + 20 files changed, 382 insertions(+), 118 deletions(-) create mode 100644 src/kind-pass/src/expand/uses.rs diff --git a/src/kind-cli/src/main.rs b/src/kind-cli/src/main.rs index aa21e763..c1a07b02 100644 --- a/src/kind-cli/src/main.rs +++ b/src/kind-cli/src/main.rs @@ -137,6 +137,7 @@ pub fn compile_in_session( if diagnostics.is_empty() { render_to_stderr(&render_config, &session, &Log::Checked(start.elapsed())); + eprintln!(); } else { render_to_stderr(&render_config, &session, &Log::Failed(start.elapsed())); eprintln!(); @@ -145,9 +146,6 @@ pub fn compile_in_session( render_to_stderr(&render_config, &session, &diagnostic) } } - - eprintln!(); - res } diff --git a/src/kind-derive/src/matching.rs b/src/kind-derive/src/matching.rs index 5d91a8f4..875e22c4 100644 --- a/src/kind-derive/src/matching.rs +++ b/src/kind-derive/src/matching.rs @@ -17,9 +17,9 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { }) }; - let mk_cons = |name: QualifiedIdent| -> Box { + let mk_cons = |name: QualifiedIdent, spine: Vec| -> Box { Box::new(Expr { - data: ExprKind::Constr(name), + data: ExprKind::Constr(name, spine), range, }) }; @@ -60,8 +60,8 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { // The type let all_args = sum.parameters.extend(&sum.indices); - let res_motive_ty = mk_app( - mk_cons(sum.name.clone()), + let res_motive_ty = mk_cons( + sum.name.clone(), all_args .iter() .cloned() @@ -110,7 +110,7 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { .map(|x| Binding::Positional(mk_var(x.name.clone()))) .collect(); - let cons_inst = mk_app(mk_cons(sum.name.add_segment(cons.name.to_str())), vars); + let cons_inst = mk_cons(sum.name.add_segment(cons.name.to_str()), vars); let mut indices_of_cons = match cons.typ.clone().map(|x| x.data) { Some(ExprKind::App(_, spine)) => spine[sum.parameters.len()..].to_vec(), diff --git a/src/kind-driver/src/resolution.rs b/src/kind-driver/src/resolution.rs index 4d23cf17..2a4db8b6 100644 --- a/src/kind-driver/src/resolution.rs +++ b/src/kind-driver/src/resolution.rs @@ -7,6 +7,8 @@ use std::collections::HashSet; use std::fs; use std::path::{Path, PathBuf}; use std::rc::Rc; +use fxhash::FxHashMap; +use kind_pass::expand::uses::expand_uses; use strsim::jaro; use kind_pass::unbound::{self}; @@ -140,14 +142,15 @@ fn parse_and_store_book_by_identifier<'a>( session: &mut Session, ident: &QualifiedIdent, book: &'a mut Book, + unbound: &mut FxHashMap> ) -> bool { if book.entries.contains_key(ident.to_string().as_str()) { return false; } match ident_to_path(&session.root, ident, true) { - Ok(Some(path)) => parse_and_store_book_by_path(session, &path, book), - Ok(None) => false, + Ok(Some(path)) => parse_and_store_book_by_path(session, &path, book, unbound), + Ok(None) => true, Err(err) => { session.diagnostic_sender.send(err).unwrap(); true @@ -159,6 +162,7 @@ fn parse_and_store_book_by_path<'a>( session: &mut Session, path: &PathBuf, book: &'a mut Book, + unbound: &mut FxHashMap> ) -> bool { if session.loaded_paths_map.contains_key(path) { return false; @@ -181,13 +185,31 @@ fn parse_and_store_book_by_path<'a>( let (mut module, mut failed) = kind_parser::parse_book(session.diagnostic_sender.clone(), ctx_id, &input); - let (_, unbound_top_level) = + let (unbound_vars, unbound_top_level) = unbound::get_module_unbound(session.diagnostic_sender.clone(), &mut module); - for idents in unbound_top_level.values() { - failed |= parse_and_store_book_by_identifier(session, &idents[0], book); + for idents in unbound_vars.values() { + unbound_variable(session, &book, idents); + failed = true; } + for idents in unbound_top_level.values() { + if idents.iter().any(|x| !x.used_by_sugar) { + let res = parse_and_store_book_by_identifier(session, &idents[0], book, unbound); + failed |= res; + if res { + for ident in idents { + if !ident.used_by_sugar { + let entry = unbound.entry(ident.to_string()).or_default(); + entry.push(ident.clone()) + } + } + } + } + } + + failed |= expand_uses(&mut module, session.diagnostic_sender.clone()); + module_to_book(session, &module, book); failed @@ -208,25 +230,15 @@ fn unbound_variable(session: &mut Session, book: &Book, idents: &[Ident]) { pub fn parse_and_store_book(session: &mut Session, path: &PathBuf) -> Option { let mut book = Book::default(); + let mut unbound = FxHashMap::default(); - let mut failed = parse_and_store_book_by_path(session, path, &mut book); + let failed = parse_and_store_book_by_path(session, path, &mut book, &mut unbound); - let (unbounds, unbounded_top) = unbound::get_book_unbound(session.diagnostic_sender.clone(), &mut book); - - for idents in unbounds.values() { - unbound_variable(session, &book, idents); - failed = true; + for (_, res) in unbound { + unbound_variable(session, &book, res.iter().map(|x| x.to_ident()).collect::>().as_slice()) } - for idents in unbounded_top.values() { - if !book.entries.contains_key(&idents[0].to_string()) { - let vec = idents.iter().map(|x| x.to_ident()).collect::>(); - unbound_variable(session, &book, vec.as_slice()); - failed = true; - } - } - - if !unbounds.is_empty() || failed { + if failed { None } else { Some(book) diff --git a/src/kind-parser/Cargo.toml b/src/kind-parser/Cargo.toml index 2d9d0a71..9267b228 100644 --- a/src/kind-parser/Cargo.toml +++ b/src/kind-parser/Cargo.toml @@ -8,4 +8,6 @@ edition = "2021" [dependencies] kind-span = { path = "../kind-span" } kind-tree = { path = "../kind-tree" } -kind-report = { path = "../kind-report" } \ No newline at end of file +kind-report = { path = "../kind-report" } + +fxhash = "0.2.1" \ No newline at end of file diff --git a/src/kind-parser/src/errors.rs b/src/kind-parser/src/errors.rs index cd166708..da0324f5 100644 --- a/src/kind-parser/src/errors.rs +++ b/src/kind-parser/src/errors.rs @@ -28,6 +28,8 @@ pub enum SyntaxError { Unclosed(Range), IgnoreRestShouldBeOnTheEnd(Range), UnusedDocString(Range), + CannotUseUse(Range), + ImportsCannotHaveAlias(Range) } fn encode_name(encode: EncodeSequence) -> &'static str { @@ -251,6 +253,34 @@ impl From for DiagnosticFrame { main: true, }], }, + SyntaxError::CannotUseUse(range) => DiagnosticFrame { + code: 14, + severity: Severity::Error, + title: "Can only use the 'use' statement in the beggining of the file".to_string(), + subtitles: vec![], + hints: vec![], + positions: vec![Marker { + position: range, + color: Color::Fst, + text: "Move it to the beggining".to_string(), + no_code: false, + main: true, + }], + }, + SyntaxError::ImportsCannotHaveAlias(range) => DiagnosticFrame { + code: 14, + severity: Severity::Error, + title: "The upper cased name cannot have an alias".to_string(), + subtitles: vec![], + hints: vec![], + positions: vec![Marker { + position: range, + color: Color::Fst, + text: "Use the entire name here!".to_string(), + no_code: false, + main: true, + }], + }, } } } diff --git a/src/kind-parser/src/expr.rs b/src/kind-parser/src/expr.rs index 15c07b02..7157f650 100644 --- a/src/kind-parser/src/expr.rs +++ b/src/kind-parser/src/expr.rs @@ -78,7 +78,7 @@ impl<'a> Parser<'a> { && self.peek(2).same_variant(&Token::Colon) } - pub fn is_named(&self) -> bool { + pub fn is_named_parameter(&self) -> bool { self.get().same_variant(&Token::LPar) && self.peek(1).is_lower_id() && self.peek(2).same_variant(&Token::Eq) @@ -126,7 +126,8 @@ impl<'a> Parser<'a> { pub fn parse_upper_id(&mut self) -> Result { let range = self.range(); - let (start, end) = eat_single!(self, Token::UpperId(start, end) => (start.clone(), end.clone()))?; + let (start, end) = + eat_single!(self, Token::UpperId(start, end) => (start.clone(), end.clone()))?; let ident = QualifiedIdent::new_static(start.as_str(), end.clone(), range); Ok(ident) } @@ -209,17 +210,29 @@ impl<'a> Parser<'a> { })) } - fn parse_data(&mut self) -> Result, SyntaxError> { + fn parse_single_upper(&mut self) -> Result, SyntaxError> { let id = self.parse_upper_id()?; let data = match id.to_string().as_str() { "Type" => ExprKind::Lit(Literal::Type), "U60" => ExprKind::Lit(Literal::U60), - _ => ExprKind::Constr(id.clone()), + _ => ExprKind::Constr(id.clone(), vec![]), }; - Ok(Box::new(Expr { - range: id.range, - data, - })) + Ok(Box::new(Expr { range: id.range, data })) + } + + fn parse_data(&mut self, multiline: bool) -> Result, SyntaxError> { + let id = self.parse_upper_id()?; + let mut range = id.range; + let data = match id.to_string().as_str() { + "Type" => ExprKind::Lit(Literal::Type), + "U60" => ExprKind::Lit(Literal::U60), + _ => { + let (range_end, spine) = self.parse_call_tail(id.range, multiline)?; + range = range_end; + ExprKind::Constr(id.clone(), spine) + } + }; + Ok(Box::new(Expr { range, data })) } fn parse_num(&mut self, num: u64) -> Result, SyntaxError> { @@ -354,8 +367,8 @@ impl<'a> Parser<'a> { pub fn parse_atom(&mut self) -> Result, SyntaxError> { self.ignore_docs(); match self.get().clone() { + Token::UpperId(_, _) => self.parse_single_upper(), Token::LowerId(_) => self.parse_var(), - Token::UpperId(_, _) => self.parse_data(), Token::Num(num) => self.parse_num(num), Token::Char(chr) => self.parse_char(chr), Token::Str(str) => self.parse_str(str), @@ -369,7 +382,7 @@ impl<'a> Parser<'a> { fn parse_binding(&mut self) -> Result { self.ignore_docs(); - if self.is_named() { + if self.is_named_parameter() { let start = self.range(); self.advance(); // '(' let name = self.parse_id()?; @@ -384,10 +397,30 @@ impl<'a> Parser<'a> { } fn parse_call(&mut self, multiline: bool) -> Result, SyntaxError> { - let head = self.parse_atom()?; - let start = head.range; + if self.get().is_upper_id() { + self.parse_data(multiline) + } else { + let head = self.parse_atom()?; + let start = head.range; + let (end, spine) = self.parse_call_tail(start, multiline)?; + if spine.is_empty() { + Ok(head) + } else { + Ok(Box::new(Expr { + data: ExprKind::App(head, spine), + range: start.mix(end), + })) + } + } + } + + fn parse_call_tail( + &mut self, + start: Range, + multiline: bool, + ) -> Result<(Range, Vec), SyntaxError> { let mut spine = Vec::new(); - let mut end = head.range; + let mut end = start; while (!self.is_linebreak() || multiline) && !self.get().same_variant(&Token::Eof) { let res = self.try_single(&|parser| parser.parse_binding())?; match res { @@ -398,14 +431,7 @@ impl<'a> Parser<'a> { None => break, } } - if spine.is_empty() { - Ok(head) - } else { - Ok(Box::new(Expr { - data: ExprKind::App(head, spine), - range: start.mix(end), - })) - } + Ok((end, spine)) } fn parse_arrow(&mut self, multiline: bool) -> Result, SyntaxError> { diff --git a/src/kind-parser/src/lexer/literals.rs b/src/kind-parser/src/lexer/literals.rs index a4ba73db..cae397c4 100644 --- a/src/kind-parser/src/lexer/literals.rs +++ b/src/kind-parser/src/lexer/literals.rs @@ -56,9 +56,9 @@ impl<'a> Lexer<'a> { /// Lex a base-10 digit. fn lex_digit(&mut self, start: usize) -> (Token, Range) { - let num = self.accumulate_while(&|x| x.is_ascii_digit()); + let num = self.accumulate_while(&|x| x.is_ascii_digit() || x == '_'); ( - Token::Num(num.parse::().unwrap()), + Token::Num(num.replace("_", "").parse::().unwrap()), self.mk_range(start), ) } @@ -67,8 +67,8 @@ impl<'a> Lexer<'a> { /// character that indicates the encoding fn lex_base(&mut self, start: usize, base: u32, err: EncodeSequence) -> (Token, Range) { self.next_char(); - let num = self.accumulate_while(&|x| x.is_digit(base)); - if let Ok(res) = u64::from_str_radix(num, base) { + let num = self.accumulate_while(&|x| x.is_digit(base) || x == '_'); + if let Ok(res) = u64::from_str_radix(&num.replace("_", ""), base) { (Token::Num(res), self.mk_range(start)) } else { ( diff --git a/src/kind-parser/src/top_level/mod.rs b/src/kind-parser/src/top_level/mod.rs index 7eab60df..ff5c5492 100644 --- a/src/kind-parser/src/top_level/mod.rs +++ b/src/kind-parser/src/top_level/mod.rs @@ -1,6 +1,9 @@ +use fxhash::FxHashMap; +use kind_tree::concrete::expr::Expr; +use kind_tree::concrete::pat::{PatIdent, Pat, PatKind}; /// Parses all of the top level structures /// like Book, Entry, Rule and Argument. -use kind_tree::concrete::{Argument, Attribute, Entry, Module, Rule, Telescope, TopLevel}; +use kind_tree::concrete::{Argument, Attribute, Entry, Module, Rule, Telescope, TopLevel, ExprKind}; use kind_tree::symbol::QualifiedIdent; use crate::errors::SyntaxError; @@ -18,6 +21,7 @@ impl<'a> Parser<'a> { pub fn is_top_level_entry_continuation(&self) -> bool { self.peek(1).same_variant(&Token::Colon) // ':' || self.peek(1).same_variant(&Token::LPar) // '(' + || self.peek(1).same_variant(&Token::LBrace) // '{' || self.peek(1).same_variant(&Token::Less) // '<' || self.peek(1).same_variant(&Token::Minus) // '-' || self.peek(1).same_variant(&Token::Plus) // '+' @@ -146,32 +150,83 @@ impl<'a> Parser<'a> { let args = self.parse_arguments()?; - self.eat_variant(Token::Colon)?; - let typ = self.parse_expr(false)?; - let mut rules = Vec::new(); - loop { - let res = self.try_single(&|parser| parser.parse_rule(ident.to_string()))?; - match res { - Some(res) => rules.push(res), - None => break, + if self.check_actual(Token::LBrace) { + let start = self.range(); + + let typ = Box::new(Expr { + data: ExprKind::Hole, + range: ident.range, + }); + + self.eat_variant(Token::LBrace)?; + + let body = self.parse_expr(true)?; + + let end = self.range(); + self.eat_closing_keyword(Token::RBrace, start)?; + + let mut rules = vec![ + Box::new(Rule { + name: ident.clone(), + pats: args.iter().map(|x| Box::new(Pat { + range: x.range, + data: PatKind::Var(PatIdent(x.name.clone())), + })).collect(), + body, + range: end, + }) + ]; + loop { + let res = self.try_single(&|parser| parser.parse_rule(ident.to_string()))?; + match res { + Some(res) => rules.push(res), + None => break, + } } - } - let end = rules.last().as_ref().map(|x| x.range).unwrap_or(typ.range); + let end = rules.last().as_ref().map(|x| x.range).unwrap_or(typ.range); - // Better error message when you have change the name of the function - if self.get().is_upper_id() && !self.is_top_level_entry_continuation() { - return Err(SyntaxError::NotAClauseOfDef(ident.range, self.range())); - } + // Better error message when you have change the name of the function + if self.get().is_upper_id() && !self.is_top_level_entry_continuation() { + return Err(SyntaxError::NotAClauseOfDef(ident.range.clone(), self.range())); + } - Ok(Entry { - name: ident, - docs, - args: Telescope::new(args), - typ, - rules, - attrs, - range: start.mix(end), - }) + Ok(Entry { + name: ident, + docs, + args: Telescope::new(args), + typ, + rules, + attrs, + range: start.mix(end), + }) + } else { + self.eat_variant(Token::Colon)?; + let typ = self.parse_expr(false)?; + let mut rules = Vec::new(); + loop { + let res = self.try_single(&|parser| parser.parse_rule(ident.to_string()))?; + match res { + Some(res) => rules.push(res), + None => break, + } + } + let end = rules.last().as_ref().map(|x| x.range).unwrap_or(typ.range); + + // Better error message when you have change the name of the function + if self.get().is_upper_id() && !self.is_top_level_entry_continuation() { + return Err(SyntaxError::NotAClauseOfDef(ident.range, self.range())); + } + + Ok(Entry { + name: ident, + docs, + args: Telescope::new(args), + typ, + rules, + attrs, + range: start.mix(end), + }) + } } pub fn parse_top_level(&mut self) -> Result { @@ -184,13 +239,56 @@ impl<'a> Parser<'a> { Ok(TopLevel::RecordType(self.parse_record_def(docs, attrs)?)) } else if self.is_top_level_entry_continuation() { Ok(TopLevel::Entry(self.parse_entry(docs, attrs)?)) + } else if self.check_actual(Token::Use) { + Err(SyntaxError::CannotUseUse(self.range())) } else { self.fail(vec![]) } } + pub fn parse_use(&mut self) -> Result<(String, String), SyntaxError> { + self.eat_variant(Token::Use)?; + let origin = self.parse_upper_id()?; + self.eat_variant(Token::As)?; + let alias = self.parse_upper_id()?; + + match (origin, alias) { + ( + QualifiedIdent { + aux: Some(_), + range, + .. + }, + _, + ) + | ( + _, + QualifiedIdent { + aux: Some(_), + range, + .. + }, + ) => Err(SyntaxError::ImportsCannotHaveAlias(range)), + (origin, alias) => Ok((origin.to_string(), alias.to_string())), + } + } + pub fn parse_module(&mut self) -> Module { let mut entries: Vec = Vec::new(); + let mut uses: FxHashMap = Default::default(); + + while self.get().same_variant(&Token::Use) { + match self.parse_use() { + Ok((origin, alias)) => { + uses.insert(alias, origin); + } + Err(err) => { + self.errs.send(err.into()).unwrap(); + self.failed = true; + break; + } + } + } while !self.get().same_variant(&Token::Eof) { match self.parse_top_level() { @@ -216,6 +314,6 @@ impl<'a> Parser<'a> { } } - Module { entries } + Module { entries, uses } } } diff --git a/src/kind-pass/src/desugar/app.rs b/src/kind-pass/src/desugar/app.rs index 71b21a61..2a3df58a 100644 --- a/src/kind-pass/src/desugar/app.rs +++ b/src/kind-pass/src/desugar/app.rs @@ -72,10 +72,9 @@ impl<'a> DesugarState<'a> { &mut self, range: Range, head: &Expr, - spine: &[Binding], ) -> Box { match &head.data { - ExprKind::Constr(entry_name) => { + ExprKind::Constr(entry_name, spine) => { let entry = self .old_book .get_count_garanteed(entry_name.to_string().as_str()); @@ -98,7 +97,8 @@ impl<'a> DesugarState<'a> { } } else if entry.arguments.len() != spine.len() { self.send_err(PassError::IncorrectArity( - head.locate(), + entry_name.range, + spine.iter().map(|x| x.locate()).collect(), entry.arguments.len(), hidden, )); @@ -168,7 +168,7 @@ impl<'a> DesugarState<'a> { span: Span::Locatable(range), }) } - _ => { + ExprKind::App(head, spine) => { let mut new_spine = Vec::new(); let new_head = self.desugar_expr(head); for arg in spine { @@ -182,6 +182,7 @@ impl<'a> DesugarState<'a> { } desugared::Expr::app(range, new_head, new_spine) } + _ => panic!("Internal Error: This function should be used with app and constr") } } } diff --git a/src/kind-pass/src/desugar/expr.rs b/src/kind-pass/src/desugar/expr.rs index 19a10538..5ecaacfc 100644 --- a/src/kind-pass/src/desugar/expr.rs +++ b/src/kind-pass/src/desugar/expr.rs @@ -227,7 +227,7 @@ impl<'a> DesugarState<'a> { pub(crate) fn desugar_expr(&mut self, expr: &expr::Expr) -> Box { use expr::ExprKind::*; match &expr.data { - Constr(_) => self.desugar_app(expr.range, expr, &[]), + Constr(_, _) | App(_, _) => self.desugar_app(expr.range, expr), All(ident, typ, body) => desugared::Expr::all( expr.range, ident.clone().unwrap_or_else(|| self.gen_name(expr.range)), @@ -248,7 +248,6 @@ impl<'a> DesugarState<'a> { } Var(ident) => desugared::Expr::var(ident.clone()), Hole => desugared::Expr::hole(expr.range, self.gen_hole()), - App(head, spine) => self.desugar_app(expr.range, head, spine), Lit(literal) => self.desugar_literal(expr.range, literal), Match(matcher) => self.desugar_match(expr.range, matcher), Let(destruct, val, next) => self.desugar_let(expr.range, destruct, val, next), diff --git a/src/kind-pass/src/desugar/top_level.rs b/src/kind-pass/src/desugar/top_level.rs index d1932a84..8802a3ff 100644 --- a/src/kind-pass/src/desugar/top_level.rs +++ b/src/kind-pass/src/desugar/top_level.rs @@ -262,6 +262,7 @@ impl<'a> DesugarState<'a> { } else if entry.arguments.len() != spine.len() { self.send_err(PassError::IncorrectArity( head.range, + spine.iter().map(|x| x.range).collect(), entry.arguments.len(), hidden, )); diff --git a/src/kind-pass/src/errors.rs b/src/kind-pass/src/errors.rs index 8be67e21..67ae987d 100644 --- a/src/kind-pass/src/errors.rs +++ b/src/kind-pass/src/errors.rs @@ -14,7 +14,7 @@ pub enum Sugar { pub enum PassError { RepeatedVariable(Range, Range), CannotUseNamed(Range, Range), - IncorrectArity(Range, usize, usize), + IncorrectArity(Range, Vec, usize, usize), DuplicatedNamed(Range, Range), LetDestructOnlyForRecord(Range), LetDestructOnlyForSum(Range), @@ -26,6 +26,7 @@ pub enum PassError { RulesWithInconsistentArity(Vec<(Range, usize)>), SugarIsBadlyImplemented(Range, Range, usize), CannotUseIrrelevant(Option, Range, Option), + CannotFindAlias(String, Range) } // TODO: A way to build an error message with methods @@ -212,28 +213,42 @@ impl From for DiagnosticFrame { main: true, }], }, - PassError::IncorrectArity(head_range, expected, hidden) => DiagnosticFrame { - code: 210, - severity: Severity::Error, - title: "Incorrect arity".to_string(), - subtitles: vec![], - hints: vec![ - if expected == 0 { - "This function expects no arguments".to_string() - } else if hidden == 0 { - format!("This function expects {} arguments", expected) - } else { - format!("This function expects {} arguments or {} (without hidden ones)", expected, expected - hidden) - } - ], - positions: vec![Marker { + PassError::IncorrectArity(head_range, got, expected, hidden) => { + let mut positions = vec![Marker { position: head_range, color: Color::Fst, text: "This function requires a fixed number of arguments".to_string(), no_code: false, main: true, - }], - }, + }]; + + for range in &got { + positions.push(Marker { + position: range.clone(), + color: Color::Snd, + text: "Remove this argument".to_string(), + no_code: false, + main: true, + }) + } + + DiagnosticFrame { + code: 210, + severity: Severity::Error, + title: "Incorrect arity, ".to_string(), + subtitles: vec![], + hints: vec![ + 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()) + } else { + format!("This function expects {} arguments or {} (without hidden ones) but got {}.", expected, expected - hidden, got.len()) + } + ], + positions + } + } PassError::SugarIsBadlyImplemented(head_range, place_range, expected) => DiagnosticFrame { code: 211, severity: Severity::Error, @@ -332,6 +347,22 @@ impl From for DiagnosticFrame { }, ], }, + PassError::CannotFindAlias(name, range) => DiagnosticFrame { + code: 214, + severity: Severity::Error, + title: "Cannot find alias".to_string(), + subtitles: vec![], + hints: vec![], + positions: vec![ + Marker { + position: range, + color: Color::Fst, + text: format!("Cannot find alias for '{}'", name), + no_code: false, + main: true, + } + ], + }, } } } diff --git a/src/kind-pass/src/expand/mod.rs b/src/kind-pass/src/expand/mod.rs index 5005a8b8..ce1cdb77 100644 --- a/src/kind-pass/src/expand/mod.rs +++ b/src/kind-pass/src/expand/mod.rs @@ -1,15 +1,12 @@ -/// Expands identifiers sum type and record definitions - -use std::collections::HashMap; +/// Expands sum type and record definitions to a lot of +/// helper definitions like eliminators and replace qualified identifiers +/// by their module names. +use std::{collections::HashMap}; use kind_derive::matching::derive_match; -use kind_tree::concrete::{Book, TopLevel, visitor::Visitor}; +use kind_tree::{concrete::{Book, TopLevel}}; -pub struct Expand; - -impl Visitor for Expand { - -} +pub mod uses; pub fn expand_book(book: &mut Book) { let mut entries = HashMap::new(); diff --git a/src/kind-pass/src/expand/uses.rs b/src/kind-pass/src/expand/uses.rs new file mode 100644 index 00000000..d80694a2 --- /dev/null +++ b/src/kind-pass/src/expand/uses.rs @@ -0,0 +1,51 @@ +/// Expands sum type and record definitions to a lot of +/// helper definitions like eliminators and replace qualified identifiers +/// by their module names. + +use std::sync::mpsc::Sender; +use fxhash::FxHashMap; +use kind_report::data::DiagnosticFrame; +use kind_tree::concrete::{visitor::Visitor, Module}; + +use crate::errors::PassError; + +pub struct Expand { + pub names: FxHashMap, + pub errors: Sender, + pub failed: bool +} + +impl Visitor for Expand { + fn visit_qualified_ident(&mut self, ident: &mut kind_tree::symbol::QualifiedIdent) { + if ident.aux.is_none() { + return; + } + let alias = match self.names.get(&ident.root.to_string()) { + Some(path) => path, + None => { + self.errors.send(PassError::CannotFindAlias(ident.root.to_string(), ident.range).into()).unwrap(); + self.failed = true; + return; + } + }; + match &ident.aux { + Some(post) => { + ident.change_root(format!("{}.{}", alias, post)); + ident.aux = None; + } + None => ident.change_root(alias.clone()), + } + } +} + +pub fn expand_uses(module: &mut Module, errors: Sender) -> bool { + let mut session = Expand { + names: module.uses.clone(), + errors, + failed: false + }; + for entry in module.entries.iter_mut() { + session.visit_top_level(entry) + } + session.failed +} diff --git a/src/kind-pass/src/unbound/mod.rs b/src/kind-pass/src/unbound/mod.rs index cff80d72..d186fcc1 100644 --- a/src/kind-pass/src/unbound/mod.rs +++ b/src/kind-pass/src/unbound/mod.rs @@ -314,7 +314,10 @@ impl Visitor for UnboundCollector { fn visit_expr(&mut self, expr: &mut Expr) { match &mut expr.data { ExprKind::Var(ident) => self.visit_ident(ident), - ExprKind::Constr(ident) => self.visit_qualified_ident(ident), + ExprKind::Constr(ident, spine) => { + self.visit_qualified_ident(ident); + visit_vec!(spine.iter_mut(), arg => self.visit_binding(arg)); + }, ExprKind::All(None, typ, body) => { self.visit_expr(typ); self.visit_expr(body); diff --git a/src/kind-report/src/report.rs b/src/kind-report/src/report.rs index 3537f6bb..6aa8f434 100644 --- a/src/kind-report/src/report.rs +++ b/src/kind-report/src/report.rs @@ -277,7 +277,7 @@ fn write_code_block<'a, T: Write + Sized>( } let code_lines: Vec<&'a str> = group_code.lines().collect(); - let mut lines = lines_set.iter().collect::>(); + let mut lines = lines_set.iter().filter(|x| **x < code_lines.len()).collect::>(); lines.sort(); for i in 0..lines.len() { diff --git a/src/kind-tree/src/concrete/expr.rs b/src/kind-tree/src/concrete/expr.rs index 771b41ba..d01c3fdf 100644 --- a/src/kind-tree/src/concrete/expr.rs +++ b/src/kind-tree/src/concrete/expr.rs @@ -113,7 +113,7 @@ pub enum ExprKind { /// Name of a variable Var(Ident), /// Name of a function/constructor - Constr(QualifiedIdent), + Constr(QualifiedIdent, Spine), /// The dependent function space (e.g. (x : Int) -> y) All(Option, Box, Box), /// The dependent product space (e.g. [x : Int] -> y) @@ -371,7 +371,12 @@ impl Display for Expr { Sigma(_, _, _) => write!(f, "({})", self.traverse_pi_types()), Lit(lit) => write!(f, "{}", lit), Var(name) => write!(f, "{}", name), - Constr(name) => write!(f, "{}", name), + Constr(head, spine) => write!( + f, + "({}{})", + head, + spine.iter().map(|x| format!(" {}", x)).collect::() + ), Lambda(binder, None, body) => write!(f, "({} => {})", binder, body), Lambda(binder, Some(typ), body) => write!(f, "(({} : {}) => {})", binder, typ, body), Pair(fst, snd) => write!(f, "($ {} {})", fst, snd), diff --git a/src/kind-tree/src/concrete/mod.rs b/src/kind-tree/src/concrete/mod.rs index 14a65c1b..7f803e98 100644 --- a/src/kind-tree/src/concrete/mod.rs +++ b/src/kind-tree/src/concrete/mod.rs @@ -170,9 +170,10 @@ impl TopLevel { /// A module is a collection of top level entries /// that contains syntatic sugars. In the future /// it will contain a HashMap to local renames. -#[derive(Clone, Debug, Default, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct Module { pub entries: Vec, + pub uses: FxHashMap } /// Metadata about entries, it's really useful when we diff --git a/src/kind-tree/src/concrete/visitor.rs b/src/kind-tree/src/concrete/visitor.rs index 80c2668e..171eafa6 100644 --- a/src/kind-tree/src/concrete/visitor.rs +++ b/src/kind-tree/src/concrete/visitor.rs @@ -365,7 +365,12 @@ pub fn walk_expr(ctx: &mut T, expr: &mut Expr) { ctx.visit_range(&mut expr.range); match &mut expr.data { ExprKind::Var(ident) => ctx.visit_ident(ident), - ExprKind::Constr(ident) => ctx.visit_qualified_ident(ident), + ExprKind::Constr(ident, spine) => { + ctx.visit_qualified_ident(ident); + for arg in spine { + ctx.visit_binding(arg); + } + }, ExprKind::All(None, typ, body) => { ctx.visit_expr(typ); ctx.visit_expr(body); diff --git a/src/kind-tree/src/symbol.rs b/src/kind-tree/src/symbol.rs index 27dfe2ec..269721da 100644 --- a/src/kind-tree/src/symbol.rs +++ b/src/kind-tree/src/symbol.rs @@ -42,6 +42,10 @@ impl QualifiedIdent { } } + pub fn change_root(&mut self, str: String) { + self.root = Symbol(str); + } + /// Avoid this function. It transforms a QualifiedIdent into a Ident pub fn to_ident(&self) -> Ident { Ident { From d301aed609586b5f74f7d04ef99541cf46e25ec8 Mon Sep 17 00:00:00 2001 From: Felipe g Date: Wed, 9 Nov 2022 11:40:35 -0300 Subject: [PATCH 5/9] fix: bugs with match and desugaring --- src/kind-checker/src/errors.rs | 11 +- src/kind-checker/src/report.rs | 33 ++++-- src/kind-cli/src/main.rs | 2 +- src/kind-derive/src/matching.rs | 52 ++++++--- src/kind-derive/src/open.rs | 149 +++++++++++++++++++++++++ src/kind-driver/src/lib.rs | 13 +++ src/kind-parser/src/errors.rs | 4 +- src/kind-parser/src/expr.rs | 10 ++ src/kind-parser/src/lexer/mod.rs | 3 +- src/kind-parser/src/lexer/tokens.rs | 4 + src/kind-parser/src/pat.rs | 11 ++ src/kind-parser/src/state.rs | 8 +- src/kind-pass/src/desugar/app.rs | 23 ++-- src/kind-pass/src/desugar/destruct.rs | 15 ++- src/kind-pass/src/desugar/expr.rs | 15 ++- src/kind-pass/src/desugar/top_level.rs | 25 +++-- src/kind-pass/src/erasure/mod.rs | 52 +++++++-- src/kind-pass/src/errors.rs | 18 +-- src/kind-pass/src/expand/mod.rs | 146 ++++++++++++++++++++++-- src/kind-pass/src/unbound/mod.rs | 17 ++- src/kind-target-hvm/src/lib.rs | 8 +- src/kind-tree/src/concrete/mod.rs | 4 +- 22 files changed, 514 insertions(+), 109 deletions(-) diff --git a/src/kind-checker/src/errors.rs b/src/kind-checker/src/errors.rs index 6bf16a12..987c9893 100644 --- a/src/kind-checker/src/errors.rs +++ b/src/kind-checker/src/errors.rs @@ -20,10 +20,13 @@ pub(crate) enum TypeError { pub fn context_to_subtitles(ctx: Context, subtitles: &mut Vec) { subtitles.push(Subtitle::LineBreak); - subtitles.push(Subtitle::Phrase( - Color::Snd, - vec![Word::White("Context:".to_string())], - )); + + if !ctx.0.is_empty() { + subtitles.push(Subtitle::Phrase( + Color::Snd, + vec![Word::White("Context:".to_string())], + )); + } let biggest = ctx .0 diff --git a/src/kind-checker/src/report.rs b/src/kind-checker/src/report.rs index 822491b5..0ee30716 100644 --- a/src/kind-checker/src/report.rs +++ b/src/kind-checker/src/report.rs @@ -54,12 +54,27 @@ fn parse_op(term: &Term) -> Result { } fn parse_name(term: &Term) -> Result { - match_opt!(*term, Term::Num { numb } => Ident::decode(numb)) + match term { + Term::Num { numb } => { + Ok(Ident::decode(*numb)) + } + Term::Ctr { name, args: _ } => { + Ok(name.to_string()) + } + _ => Err("Error while matching opt".to_string()) + } } fn parse_qualified(term: &Term) -> Result { - let name = match_opt!(*term, Term::Num { numb } => Ident::decode(numb))?; - Ok(QualifiedIdent::new_static(&name, None, Range::ghost_range())) + match term { + Term::Num { numb } => { + Ok(QualifiedIdent::new_static(&Ident::decode(*numb), None, Range::ghost_range())) + } + Term::Ctr { name, args: _ } => { + Ok(QualifiedIdent::new_static(&name, None, Range::ghost_range())) + } + _ => Err("Error while matching opt".to_string()) + } } fn parse_expr(term: &Term) -> Result, String> { @@ -113,12 +128,12 @@ fn parse_all_expr( vec![parse_all_expr(names, &args[2])?], )), "Kind.Quoted.ctr" => Ok(Expr::ctr( - parse_orig(&args[0])?, - parse_qualified(&args[1])?, + parse_orig(&args[1])?, + parse_qualified(&args[0])?, { let mut res = Vec::new(); - for arg in &args[1..] { - res.push(parse_all_expr(names.clone(), arg)?); + for arg in parse_list(&args[2])? { + res.push(parse_all_expr(names.clone(), &arg)?); } res }, @@ -143,7 +158,7 @@ fn parse_all_expr( parse_all_expr(names.clone(), &args[2])?, parse_all_expr(names, &args[3])?, )), - _ => Err("Unexpected tag on transforming quoted term".to_string()), + tag => Err(format!("Unexpected tag on transforming quoted term {:?}", tag)), }, _ => Err("Unexpected term on transforming quoted term".to_string()), } @@ -161,7 +176,7 @@ fn parse_list(term: &Term) -> Result>, String> { vec.push(args[0].clone()); cur = &args[1]; } else { - return Err("Unexpected constructor on list".to_string()); + return Err(format!("Unexpected constructor on list '{:?}'", name)); } } _ => return Err("Unexpected value on list".to_string()), diff --git a/src/kind-cli/src/main.rs b/src/kind-cli/src/main.rs index c1a07b02..24b887a5 100644 --- a/src/kind-cli/src/main.rs +++ b/src/kind-cli/src/main.rs @@ -197,7 +197,7 @@ fn main() { } Command::GenChecker { file } => { compile_in_session(render_config, root, file.clone(), &mut |session| { - driver::erase_book(session, &PathBuf::from(file.clone())) + driver::check_erasure_book(session, &PathBuf::from(file.clone())) }).and_then(|res| { print!("{}", driver::generate_checker(&res)); Some(res) diff --git a/src/kind-derive/src/matching.rs b/src/kind-derive/src/matching.rs index 875e22c4..a367e23c 100644 --- a/src/kind-derive/src/matching.rs +++ b/src/kind-derive/src/matching.rs @@ -24,7 +24,7 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { }) }; - let mk_app = |left: Box, right: Vec| -> Box { + let mk_app = |left: Box, right: Vec, range: Range| -> Box { Box::new(Expr { data: ExprKind::App(left, right), range, @@ -56,7 +56,7 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { for arg in sum.indices.iter() { types.push(arg.to_implicit()) } - + // The type let all_args = sum.parameters.extend(&sum.indices); @@ -69,6 +69,13 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { .collect(), ); + let parameter_names: Vec = sum + .parameters + .iter() + .map(|x| Binding::Positional(mk_var(x.name.clone()))) + .collect(); + + let indice_names: Vec = sum .indices .iter() @@ -89,7 +96,7 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { let motive_ident = Ident::new_static("motive", range); - let motive_type = sum.indices.iter().rfold( + let motive_type = sum.parameters.extend(&sum.indices).iter().rfold( mk_pi(Ident::new_static("_val", range), res_motive_ty, mk_typ()), |out, arg| mk_pi(arg.name.clone(), arg.typ.clone().unwrap_or(mk_typ()), out), ); @@ -102,23 +109,26 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { range, }); + let params = sum.parameters.map(|x| Binding::Positional(mk_var(x.name.clone()))); + // Constructors type for cons in &sum.constructors { - let vars = cons + let vars: Vec = cons .args .iter() .map(|x| Binding::Positional(mk_var(x.name.clone()))) .collect(); - let cons_inst = mk_cons(sum.name.add_segment(cons.name.to_str()), vars); + let cons_inst = mk_cons(sum.name.add_segment(cons.name.to_str()), [params.as_slice(), vars.as_slice()].concat()); let mut indices_of_cons = match cons.typ.clone().map(|x| x.data) { - Some(ExprKind::App(_, spine)) => spine[sum.parameters.len()..].to_vec(), - _ => indice_names.clone(), + Some(ExprKind::Constr(_, spine)) => spine.to_vec(), + _ => [parameter_names.as_slice(), indice_names.as_slice()].concat(), }; indices_of_cons.push(Binding::Positional(cons_inst)); - let cons_tipo = mk_app(mk_var(motive_ident.clone()), indices_of_cons); + + let cons_tipo = mk_app(mk_var(motive_ident.clone()), indices_of_cons, range); let cons_type = cons.args.iter().rfold(cons_tipo, |out, arg| { mk_pi( @@ -137,9 +147,9 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { }); } - let mut res: Vec = indice_names; + let mut res: Vec = [parameter_names.as_slice(), indice_names.as_slice()].concat(); res.push(Binding::Positional(mk_var(Ident::generate("scrutinizer")))); - let ret_ty = mk_app(mk_var(motive_ident), res); + let ret_ty = mk_app(mk_var(motive_ident), res, range); let mut rules = Vec::new(); @@ -147,16 +157,19 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { let cons_ident = sum.name.add_segment(cons.name.to_str()); let mut pats: Vec> = Vec::new(); - let spine: Vec = cons - .args - .iter() + let spine_params: Vec = sum.parameters.extend(&cons.args) .map(|x| x.name.with_name(|f| format!("{}_", f))) - .collect(); + .to_vec(); + + + let spine: Vec = cons.args + .map(|x| x.name.with_name(|f| format!("{}_", f))) + .to_vec(); pats.push(Box::new(Pat { data: concrete::pat::PatKind::App( cons_ident.clone(), - spine + spine_params .iter() .cloned() .map(|x| { @@ -188,18 +201,19 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { .iter() .map(|arg| Binding::Positional(mk_var(arg.clone()))) .collect(), + cons.name.range ); rules.push(Box::new(Rule { name: name.clone(), pats, body, - range, + range: cons.name.range, })) } // Rules - Entry { + let entry = Entry { name, docs: Vec::new(), args: types, @@ -207,5 +221,7 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { rules, range, attrs: Vec::new(), - } + }; + + entry } diff --git a/src/kind-derive/src/open.rs b/src/kind-derive/src/open.rs index 8b137891..0e2f0890 100644 --- a/src/kind-derive/src/open.rs +++ b/src/kind-derive/src/open.rs @@ -1 +1,150 @@ +///! Module to derive a "open" function for records. +use kind_span::Range; +use kind_tree::concrete::expr::Expr; +use kind_tree::concrete::pat::{Pat, PatIdent}; +use kind_tree::concrete::*; +use kind_tree::concrete::{self}; +use kind_tree::symbol::{Ident, QualifiedIdent}; + +pub fn derive_open(range: Range, sum: &RecordDecl) -> concrete::Entry { + let mk_var = |name: Ident| -> Box { + Box::new(Expr { + data: ExprKind::Var(name), + range, + }) + }; + + let mk_cons = |name: QualifiedIdent, spine: Vec| -> Box { + Box::new(Expr { + data: ExprKind::Constr(name, spine), + range, + }) + }; + + let mk_app = |left: Box, right: Vec| -> Box { + Box::new(Expr { + data: ExprKind::App(left, right), + range, + }) + }; + + let mk_pi = |name: Ident, left: Box, right: Box| -> Box { + Box::new(Expr { + data: ExprKind::All(Some(name), left, right), + range, + }) + }; + + let name = sum.name.add_segment("open"); + + let mut types = Telescope::default(); + + for arg in sum.parameters.iter() { + types.push(arg.to_implicit()) + } + + // The type + + let all_args = sum.parameters.clone(); + let res_motive_ty = mk_cons( + sum.name.clone(), + all_args + .iter() + .cloned() + .map(|x| Binding::Positional(mk_var(x.name))) + .collect(), + ); + + types.push(Argument { + hidden: true, + erased: true, + name: Ident::generate("_res"), + typ: None, + range, + }); + + let cons_tipo = mk_var(Ident::generate("_res")); + + let cons_type = sum.fields.iter().rfold(cons_tipo, |out, (name, _, typ)| { + mk_pi( + name.clone(), + typ.clone(), + out, + ) + }); + + // Sccrutinzies + + types.push(Argument { + hidden: false, + erased: false, + name: Ident::generate("scrutinizer"), + typ: Some(res_motive_ty.clone()), + range, + }); + + types.push(Argument { + hidden: false, + erased: false, + name: Ident::generate("fun"), + typ: Some(cons_type), + range, + }); + + // Motive with indices + + let ret_ty = mk_var(Ident::generate("_res")); + + let mut pats: Vec> = Vec::new(); + + let spine: Vec = sum + .fields + .iter() + .map(|(name, _, _)| name.with_name(|f| format!("{}_", f))) + .collect(); + + pats.push(Box::new(Pat { + data: concrete::pat::PatKind::App( + sum.name.add_segment(sum.constructor.to_str()).clone(), + spine + .iter() + .cloned() + .map(|x| { + Box::new(Pat { + data: concrete::pat::PatKind::Var(PatIdent(x)), + range, + }) + }) + .collect(), + ), + range, + })); + + pats.push(Box::new(Pat { + data: concrete::pat::PatKind::Var(PatIdent(Ident::generate("fun_"))), + range, + })); + + let body = mk_app( + mk_var(Ident::generate("fun_")), + spine + .iter() + .map(|arg| Binding::Positional(mk_var(arg.clone()))) + .collect(), + ); + + let rules = vec![ + Box::new(Rule { name: name.clone(), pats, body, range }) + ]; + + Entry { + name, + docs: Vec::new(), + args: types, + typ: ret_ty, + rules, + range, + attrs: Vec::new(), + } +} diff --git a/src/kind-driver/src/lib.rs b/src/kind-driver/src/lib.rs index 2d86e177..fc31328d 100644 --- a/src/kind-driver/src/lib.rs +++ b/src/kind-driver/src/lib.rs @@ -22,6 +22,7 @@ impl FileCache for Session { pub fn type_check_book(session: &mut Session, path: &PathBuf) -> Option { let concrete_book = to_book(session, path)?; let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?; + let succeeded = checker::type_check(&desugared_book, session.diagnostic_sender.clone()); if !succeeded { @@ -55,6 +56,18 @@ pub fn erase_book(session: &mut Session, path: &PathBuf) -> Option Option { + let concrete_book = to_book(session, path)?; + let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?; + erasure::erase_book( + &desugared_book, + session.diagnostic_sender.clone(), + HashSet::from_iter(vec!["Main".to_string()]), + )?; + Some(desugared_book) +} + pub fn compile_book_to_hvm(session: &mut Session, path: &PathBuf) -> Option { erase_book(session, path).map(kind_target_hvm::compile_book) } diff --git a/src/kind-parser/src/errors.rs b/src/kind-parser/src/errors.rs index da0324f5..990ed007 100644 --- a/src/kind-parser/src/errors.rs +++ b/src/kind-parser/src/errors.rs @@ -225,10 +225,10 @@ impl From for DiagnosticFrame { main: true, }], }, - SyntaxError::UnexpectedToken(_token, range, _expect) => DiagnosticFrame { + SyntaxError::UnexpectedToken(token, range, _expect) => DiagnosticFrame { code: 13, severity: Severity::Error, - title: "Unexpected token.".to_string(), + title: format!("Unexpected token {:?}.", token), subtitles: vec![], hints: vec![], positions: vec![Marker { diff --git a/src/kind-parser/src/expr.rs b/src/kind-parser/src/expr.rs index 7157f650..b2680746 100644 --- a/src/kind-parser/src/expr.rs +++ b/src/kind-parser/src/expr.rs @@ -375,6 +375,7 @@ impl<'a> Parser<'a> { Token::Help(str) => self.parse_help(str), Token::LBracket => self.parse_list(), Token::LPar => self.parse_paren(), + Token::Hole => self.parse_hole(), Token::Float(_, _) => todo!(), _ => self.fail(vec![Token::LowerId("".to_string())]), } @@ -665,6 +666,15 @@ impl<'a> Parser<'a> { })) } + fn parse_hole(&mut self) -> Result, SyntaxError> { + let start = self.range(); + self.advance(); // '_' + Ok(Box::new(Expr { + data: ExprKind::Hole, + range: start, + })) + } + fn parse_if(&mut self) -> Result, SyntaxError> { let start = self.range(); self.advance(); // 'if' diff --git a/src/kind-parser/src/lexer/mod.rs b/src/kind-parser/src/lexer/mod.rs index 7f216a47..33bffb81 100644 --- a/src/kind-parser/src/lexer/mod.rs +++ b/src/kind-parser/src/lexer/mod.rs @@ -29,7 +29,7 @@ fn is_valid_id(chr: char) -> bool { } fn is_valid_upper_start(chr: char) -> bool { - matches!(chr, 'A'..='Z' | '_') + matches!(chr, 'A'..='Z') } fn is_valid_id_start(chr: char) -> bool { @@ -51,6 +51,7 @@ impl<'a> Lexer<'a> { pub fn to_keyword(data: &str) -> Token { match data { + "_" => Token::Hole, "ask" => Token::Ask, "do" => Token::Do, "if" => Token::If, diff --git a/src/kind-parser/src/lexer/tokens.rs b/src/kind-parser/src/lexer/tokens.rs index b48cbc61..facfaf96 100644 --- a/src/kind-parser/src/lexer/tokens.rs +++ b/src/kind-parser/src/lexer/tokens.rs @@ -101,4 +101,8 @@ impl Token { pub fn is_num(&self) -> bool { matches!(self, Token::Num(_)) } + + pub fn is_eof(&self) -> bool { + matches!(self, Token::Eof) + } } diff --git a/src/kind-parser/src/pat.rs b/src/kind-parser/src/pat.rs index 4c1a8b9f..56b9cf14 100644 --- a/src/kind-parser/src/pat.rs +++ b/src/kind-parser/src/pat.rs @@ -68,6 +68,15 @@ impl<'a> Parser<'a> { })) } + pub fn parse_pat_hole(&mut self) -> Result, SyntaxError> { + let range = self.range(); + self.eat_variant(Token::Hole)?; + Ok(Box::new(Pat { + range, + data: PatKind::Hole, + })) + } + fn parse_pat_list(&mut self) -> Result, SyntaxError> { let range = self.range(); self.advance(); // '[' @@ -123,6 +132,8 @@ impl<'a> Parser<'a> { self.parse_pat_single_cons() } else if self.check_actual(Token::LBrace) { self.parse_pat_list() + } else if self.check_actual(Token::Hole) { + self.parse_pat_hole() } else { self.fail(vec![]) } diff --git a/src/kind-parser/src/state.rs b/src/kind-parser/src/state.rs index 2267e9be..9830e95e 100644 --- a/src/kind-parser/src/state.rs +++ b/src/kind-parser/src/state.rs @@ -86,8 +86,12 @@ impl<'a> Parser<'a> { } pub fn eat_closing_keyword(&mut self, expect: Token, range: Range) -> Result<(), SyntaxError> { - if !self.check_and_eat(expect) { - Err(SyntaxError::Unclosed(range)) + if !self.check_and_eat(expect.clone()) { + if self.get().is_eof() { + Err(SyntaxError::Unclosed(range)) + } else { + self.fail(vec![expect]) + } } else { Ok(()) } diff --git a/src/kind-pass/src/desugar/app.rs b/src/kind-pass/src/desugar/app.rs index 2a3df58a..6839510c 100644 --- a/src/kind-pass/src/desugar/app.rs +++ b/src/kind-pass/src/desugar/app.rs @@ -4,7 +4,7 @@ use kind_tree::concrete::expr::Expr; use kind_tree::concrete::{Binding, ExprKind}; use kind_tree::desugared; -use kind_tree::symbol::{QualifiedIdent}; +use kind_tree::symbol::QualifiedIdent; use crate::errors::PassError; @@ -16,6 +16,7 @@ impl<'a> DesugarState<'a> { range: Range, head: QualifiedIdent, spine: Vec>, + create_var: bool, ) -> Option>> { let entry = self.old_book.get_count_garanteed(head.to_string().as_str()); @@ -27,7 +28,11 @@ impl<'a> DesugarState<'a> { let mut spine_iter = spine.iter(); for arg in entry.arguments.iter() { if arg.hidden { - arguments.push(self.gen_hole_expr()) + if create_var { + arguments.push(desugared::Expr::var(self.gen_name(arg.range))) + } else { + arguments.push(self.gen_hole_expr()) + } } else { arguments.push(spine_iter.next().unwrap().to_owned()) } @@ -49,8 +54,9 @@ impl<'a> DesugarState<'a> { range: Range, head: QualifiedIdent, spine: Vec>, + create_var_on_hidden: bool, ) -> Box { - match self.make_desugared_spine(range, head.clone(), spine) { + match self.make_desugared_spine(range, head.clone(), spine, create_var_on_hidden) { Some(spine) => desugared::Expr::ctr(range, head, spine), None => desugared::Expr::err(range), } @@ -61,18 +67,15 @@ impl<'a> DesugarState<'a> { range: Range, head: QualifiedIdent, spine: Vec>, + create_var_on_hidden: bool, ) -> Box { - match self.make_desugared_spine(range, head.clone(), spine) { + match self.make_desugared_spine(range, head.clone(), spine, create_var_on_hidden) { Some(spine) => desugared::Expr::fun(range, head, spine), None => desugared::Expr::err(range), } } - pub(crate) fn desugar_app( - &mut self, - range: Range, - head: &Expr, - ) -> Box { + pub(crate) fn desugar_app(&mut self, range: Range, head: &Expr) -> Box { match &head.data { ExprKind::Constr(entry_name, spine) => { let entry = self @@ -182,7 +185,7 @@ impl<'a> DesugarState<'a> { } desugared::Expr::app(range, new_head, new_spine) } - _ => panic!("Internal Error: This function should be used with app and constr") + _ => panic!("Internal Error: This function should be used with app and constr"), } } } diff --git a/src/kind-pass/src/desugar/destruct.rs b/src/kind-pass/src/desugar/destruct.rs index 03cb53d5..48d5f18d 100644 --- a/src/kind-pass/src/desugar/destruct.rs +++ b/src/kind-pass/src/desugar/destruct.rs @@ -60,16 +60,17 @@ impl<'a> DesugarState<'a> { pub(crate) fn desugar_destruct( &mut self, + range: Range, binding: &expr::Destruct, val: Box, next: &dyn Fn(&mut Self) -> Box, on_ident: &dyn Fn(&mut Self, &Ident) -> Box, ) -> Box { match binding { - Destruct::Destruct(destruct_range, typ, case, jump_rest) => { - let entry = self.old_book.get_entry_garanteed(&typ.to_string()); + Destruct::Destruct(_, typ, case, jump_rest) => { + let entry = self.old_book.entries.get(&typ.to_string()); - let record = if let TopLevel::RecordType(record) = entry { + let record = if let Some(TopLevel::RecordType(record)) = entry { record } else { self.send_err(PassError::LetDestructOnlyForRecord(typ.range)); @@ -101,10 +102,10 @@ impl<'a> DesugarState<'a> { let spine = vec![ val, - desugared::Expr::unfold_lambda(*destruct_range, &arguments, next(self)), + desugared::Expr::unfold_lambda(range, &arguments, next(self)), ]; - self.mk_desugared_fun(*destruct_range, open_id, spine) + self.mk_desugared_fun(range, open_id, spine, false) } Destruct::Ident(name) => on_ident(self, name), } @@ -119,6 +120,7 @@ impl<'a> DesugarState<'a> { ) -> Box { let res_val = self.desugar_expr(val); self.desugar_destruct( + next.range, binding, res_val, &|this| this.desugar_expr(next), @@ -138,7 +140,7 @@ impl<'a> DesugarState<'a> { range: Range, match_: &expr::Match, ) -> Box { - let entry = self.old_book.get_entry_garanteed(&match_.typ.to_string()); + let entry = self.old_book.entries.get(&match_.typ.to_string()).unwrap(); let sum = if let TopLevel::SumType(sum) = entry { sum @@ -234,6 +236,7 @@ impl<'a> DesugarState<'a> { match_.typ.range, match_id, [prefix.as_slice(), lambdas.as_slice()].concat(), + false, ) } } diff --git a/src/kind-pass/src/desugar/expr.rs b/src/kind-pass/src/desugar/expr.rs index 5ecaacfc..51d7e637 100644 --- a/src/kind-pass/src/desugar/expr.rs +++ b/src/kind-pass/src/desugar/expr.rs @@ -51,6 +51,7 @@ impl<'a> DesugarState<'a> { range, bind_ident.clone(), vec![expr, desugared::Expr::lambda(range, name, next)], + false ) }; @@ -67,6 +68,7 @@ impl<'a> DesugarState<'a> { let name = self.gen_name(sttm.range); let res_destruct = self.desugar_destruct( + next.range, &concrete::Destruct::Destruct(*a, b.to_owned(), c.to_owned(), *d), desugared::Expr::var(name.clone()), &|this| this.desugar_sttm(bind_ident, pure_ident, next), @@ -83,6 +85,7 @@ impl<'a> DesugarState<'a> { concrete::SttmKind::Let(destruct, val, next) => { let res_val = self.desugar_expr(&val.clone()); self.desugar_destruct( + next.range, destruct, res_val, &|this| this.desugar_sttm(bind_ident, pure_ident, next), @@ -98,7 +101,7 @@ impl<'a> DesugarState<'a> { } concrete::SttmKind::Return(expr) => { let res_expr = self.desugar_expr(expr); - self.mk_desugared_fun(expr.locate(), pure_ident.clone(), vec![res_expr]) + self.mk_desugared_fun(expr.locate(), pure_ident.clone(), vec![res_expr], false) } concrete::SttmKind::RetExpr(expr) => self.desugar_expr(expr), } @@ -149,7 +152,7 @@ impl<'a> DesugarState<'a> { desugared::Expr::lambda(range, name, self.desugar_expr(body)), ]; - self.mk_desugared_ctr(range, sigma, spine) + self.mk_desugared_ctr(range, sigma, spine, false) } pub(crate) fn desugar_list( @@ -171,10 +174,10 @@ impl<'a> DesugarState<'a> { } expr.iter().rfold( - self.mk_desugared_ctr(range, nil_ident, Vec::new()), + self.mk_desugared_ctr(range, nil_ident, Vec::new(), false), |res, elem| { let spine = vec![self.desugar_expr(elem), res]; - self.mk_desugared_ctr(range, cons_ident.clone(), spine) + self.mk_desugared_ctr(range, cons_ident.clone(), spine, false) }, ) } @@ -201,7 +204,7 @@ impl<'a> DesugarState<'a> { self.desugar_expr(else_), ]; - self.mk_desugared_fun(range, bool_ident, spine) + self.mk_desugared_fun(range, bool_ident, spine, false) } pub(crate) fn desugar_pair( @@ -221,7 +224,7 @@ impl<'a> DesugarState<'a> { let spine = vec![self.desugar_expr(fst), self.desugar_expr(snd)]; - self.mk_desugared_ctr(range, sigma_new, spine) + self.mk_desugared_ctr(range, sigma_new, spine, false) } pub(crate) fn desugar_expr(&mut self, expr: &expr::Expr) -> Box { diff --git a/src/kind-pass/src/desugar/top_level.rs b/src/kind-pass/src/desugar/top_level.rs index 8802a3ff..23e9c6c0 100644 --- a/src/kind-pass/src/desugar/top_level.rs +++ b/src/kind-pass/src/desugar/top_level.rs @@ -90,7 +90,7 @@ impl<'a> DesugarState<'a> { .map(|x| desugared::Expr::var(x.name.clone())) .collect::>>(); - desugared::Expr::ctr(sum_type.name.range, sum_type.name.clone(), args) + desugared::Expr::ctr(cons.name.range, sum_type.name.clone(), args) } }; @@ -105,9 +105,10 @@ impl<'a> DesugarState<'a> { typ, rules: Vec::new(), attrs: Vec::new(), - span: Span::Locatable(sum_type.name.range), + span: Span::Locatable(cons.name.range), }; + self.new_book .entrs .insert(cons_ident.to_string(), Box::new(data_constructor)); @@ -198,7 +199,7 @@ impl<'a> DesugarState<'a> { let spine = vec![self.desugar_pat(fst), self.desugar_pat(snd)]; - self.mk_desugared_ctr(range, sigma_new, spine) + self.mk_desugared_ctr(range, sigma_new, spine, true) } pub fn desugar_list_pat( @@ -220,10 +221,10 @@ impl<'a> DesugarState<'a> { } expr.iter().rfold( - self.mk_desugared_ctr(range, nil_ident, Vec::new()), + self.mk_desugared_ctr(range, nil_ident, Vec::new(), true), |res, elem| { let spine = vec![self.desugar_pat(elem), res]; - self.mk_desugared_ctr(range, cons_ident.clone(), spine) + self.mk_desugared_ctr(range, cons_ident.clone(), spine, true) }, ) } @@ -240,7 +241,7 @@ impl<'a> DesugarState<'a> { if !entry.is_ctr { // TODO: Not sure if i should just throw an error? // We are not requiring that the thing is specifically a constructor - panic!("Incomplete Design: Oh no!") + //panic!("Incomplete Design: Oh no! {}", head) } let (hidden, _erased) = entry.arguments.count_implicits(); @@ -253,13 +254,15 @@ impl<'a> DesugarState<'a> { let mut count = 0; for i in 0..entry.arguments.len() { if entry.arguments[i].hidden { - new_spine.push(self.gen_hole_expr()) + let name = self.gen_name(entry.arguments[i].range); + new_spine.push(desugared::Expr::var(name)) } else { new_spine.push(self.desugar_pat(&spine[count])); count += 1; } } } else if entry.arguments.len() != spine.len() { + println!("{}", pat); self.send_err(PassError::IncorrectArity( head.range, spine.iter().map(|x| x.range).collect(), @@ -274,9 +277,12 @@ impl<'a> DesugarState<'a> { } desugared::Expr::ctr(pat.range, head.clone(), new_spine) } + concrete::pat::PatKind::Hole => { + let name = self.gen_name(pat.range); + desugared::Expr::var(name) + }, concrete::pat::PatKind::Var(ident) => desugared::Expr::var(ident.0.clone()), concrete::pat::PatKind::Num(n) => desugared::Expr::num(pat.range, *n), - concrete::pat::PatKind::Hole => desugared::Expr::hole(pat.range, self.gen_hole()), concrete::pat::PatKind::Pair(fst, snd) => self.desugar_pair_pat(pat.range, fst, snd), concrete::pat::PatKind::List(ls) => self.desugar_list_pat(pat.range, ls), concrete::pat::PatKind::Str(string) => { @@ -339,6 +345,9 @@ impl<'a> DesugarState<'a> { } pub fn desugar_entry(&mut self, entry: &concrete::Entry) { + + self.name_count = 0; + let rules = entry .rules .iter() diff --git a/src/kind-pass/src/erasure/mod.rs b/src/kind-pass/src/erasure/mod.rs index abd50690..019df77f 100644 --- a/src/kind-pass/src/erasure/mod.rs +++ b/src/kind-pass/src/erasure/mod.rs @@ -146,7 +146,14 @@ impl<'a> ErasureState<'a> { self.holes[hole.1] = Some(t); true } else { - self.unify_hole(range, (hole.0, n), right, visited, inverted, relevance_unify) + self.unify_hole( + range, + (hole.0, n), + right, + visited, + inverted, + relevance_unify, + ) } } (_, Relevance::Relevant) => true, @@ -176,9 +183,14 @@ impl<'a> ErasureState<'a> { (_, Relevance::Hole(hole)) => { self.unify_hole(range, (right.0, hole), left, visited, true, relevance_unify) } - (Relevance::Hole(hole), _) => { - self.unify_hole(range, (left.0, hole), right, visited, false, relevance_unify) - } + (Relevance::Hole(hole), _) => self.unify_hole( + range, + (left.0, hole), + right, + visited, + false, + relevance_unify, + ), (Relevance::Irrelevant, Relevance::Irrelevant) | (Relevance::Irrelevant, Relevance::Relevant) @@ -234,7 +246,7 @@ impl<'a> ErasureState<'a> { .zip(irrelevances) .for_each(|(arg, relev)| self.erase_pat(relev, arg)); } - _ => panic!("Internal Error: Not a pattern"), + res => panic!("Internal Error: Not a pattern {:?}", res), } } @@ -243,7 +255,17 @@ impl<'a> ErasureState<'a> { match &expr.data { Typ | U60 | Num(_) | Str(_) | Err => Box::new(expr.clone()), - Hole(_) | Hlp(_) => Box::new(expr.clone()), + Hole(_) | Hlp(_) => { + match &expr.span { + kind_span::Span::Generated => Box::new(expr.clone()), + kind_span::Span::Locatable(span) => { + if !self.unify(span.clone(), on.clone(), (None, Relevance::Irrelevant), false) { + self.err_irrelevant(None, span.clone(), None) + } + Box::new(expr.clone()) + }, + } + }, Var(name) => { let relev = self.ctx.get(&name.to_string()).unwrap(); let declared_ty = (relev.1).0; @@ -316,13 +338,23 @@ impl<'a> ErasureState<'a> { self.err_irrelevant(None, head.range, None) } - let spine = spine.iter().zip(args).map(|(expr, arg)| { - self.erase_expr(&(Some(arg.span), erasure_to_relevance(arg.erased)), expr) - }); + let spine = spine + .iter() + .zip(args) + .map(|(expr, arg)| { + ( + self.erase_expr( + &(Some(arg.span), erasure_to_relevance(arg.erased)), + expr, + ), + arg, + ) + }) + .filter(|(_, arg)| !arg.erased); Box::new(Expr { span: expr.span, - data: ExprKind::Fun(head.clone(), spine.collect()), + data: ExprKind::Fun(head.clone(), spine.map(|(expr, _)| expr).collect()), }) } Ctr(head, spine) => { diff --git a/src/kind-pass/src/errors.rs b/src/kind-pass/src/errors.rs index 67ae987d..dcfef199 100644 --- a/src/kind-pass/src/errors.rs +++ b/src/kind-pass/src/errors.rs @@ -214,7 +214,7 @@ impl From for DiagnosticFrame { }], }, PassError::IncorrectArity(head_range, got, expected, hidden) => { - let mut positions = vec![Marker { + let positions = vec![Marker { position: head_range, color: Color::Fst, text: "This function requires a fixed number of arguments".to_string(), @@ -222,20 +222,10 @@ impl From for DiagnosticFrame { main: true, }]; - for range in &got { - positions.push(Marker { - position: range.clone(), - color: Color::Snd, - text: "Remove this argument".to_string(), - no_code: false, - main: true, - }) - } - DiagnosticFrame { code: 210, severity: Severity::Error, - title: "Incorrect arity, ".to_string(), + title: "Incorrect arity.".to_string(), subtitles: vec![], hints: vec![ if expected == 0 { @@ -327,9 +317,9 @@ impl From for DiagnosticFrame { PassError::RepeatedVariable(first_decl, last_decl) => DiagnosticFrame { code: 214, severity: Severity::Error, - title: "Repeated variable".to_string(), + title: "Repeated name".to_string(), subtitles: vec![], - hints: vec!["Rename one of the variables".to_string()], + hints: vec!["Rename one of the occurences".to_string()], positions: vec![ Marker { position: last_decl, diff --git a/src/kind-pass/src/expand/mod.rs b/src/kind-pass/src/expand/mod.rs index ce1cdb77..8557f939 100644 --- a/src/kind-pass/src/expand/mod.rs +++ b/src/kind-pass/src/expand/mod.rs @@ -1,27 +1,151 @@ +use fxhash::FxHashMap; +use kind_derive::matching::derive_match; +use kind_derive::open::derive_open; +use kind_tree::concrete::{ + self, expr::Expr, Argument, Binding, Book, Entry, ExprKind, Literal, RecordDecl, SumTypeDecl, + Telescope, TopLevel, EntryMeta, +}; /// Expands sum type and record definitions to a lot of /// helper definitions like eliminators and replace qualified identifiers /// by their module names. - -use std::{collections::HashMap}; -use kind_derive::matching::derive_match; -use kind_tree::{concrete::{Book, TopLevel}}; - pub mod uses; +pub fn expand_record_type(book: &mut FxHashMap, rec_type: &RecordDecl) { + let type_constructor = Entry { + name: rec_type.name.clone(), + args: rec_type.parameters.clone(), + docs: rec_type.docs.clone(), + typ: Box::new(Expr { + data: ExprKind::Lit(Literal::Type), + range: rec_type.name.range, + }), + rules: Vec::new(), + range: rec_type.name.range, + attrs: rec_type.attrs.clone(), + }; + + book.insert(rec_type.name.to_string(), (type_constructor, rec_type.extract_book_info())); + + let irrelevant_params = rec_type.parameters.map(|x| x.to_implicit()); + + let args = irrelevant_params + .iter() + .map(|x| { + Binding::Positional(Box::new(Expr { + data: ExprKind::Var(x.name.clone()), + range: x.range, + })) + }) + .collect::>(); + + let typ = Box::new(Expr { + data: ExprKind::Constr(rec_type.name.clone(), args), + range: rec_type.name.range, + }); + + let cons_ident = rec_type.name.add_segment(rec_type.constructor.to_str()); + + let data_constructor = Entry { + name: cons_ident.clone(), + args: irrelevant_params.extend(&Telescope::new(rec_type.fields.clone()).map( + |(ident, _, ty)| Argument { + hidden: false, + erased: false, + name: ident.clone(), + typ: Some(ty.clone()), + range: ident.range, + }, + )), + typ, + rules: Vec::new(), + range: rec_type.constructor.range, + attrs: Vec::new(), + docs: vec![], + }; + + book.insert(cons_ident.to_string(), (data_constructor, rec_type.extract_book_info_of_constructor())); +} + +pub fn expand_sum_type(book: &mut FxHashMap, sum_type: &SumTypeDecl) { + let params = sum_type.parameters.clone(); + let indices = sum_type.indices.clone(); + + let type_constructor = Entry { + name: sum_type.name.clone(), + args: sum_type.parameters.extend(&sum_type.indices), + docs: sum_type.docs.clone(), + typ: Box::new(Expr { + data: ExprKind::Lit(Literal::Type), + range: sum_type.name.range, + }), + rules: Vec::new(), + range: sum_type.name.range, + attrs: sum_type.attrs.clone(), + }; + + let extracted = sum_type.extract_book_info(); + book.insert(sum_type.name.to_string(), (type_constructor, extracted)); + + let irrelevant_params = params.map(|x| x.to_implicit()); + let irelevant_indices = indices.map(|x| x.to_implicit()); + + for cons in &sum_type.constructors { + let cons_ident = sum_type.name.add_segment(cons.name.to_str()); + + let pre_indices = if cons.typ.is_none() { + irelevant_indices.clone() + } else { + Telescope::new(vec![]) + }; + + let typ = cons.typ.clone().unwrap_or_else(|| { + let args = params.extend(&pre_indices).map(|x| { + concrete::Binding::Positional(Box::new(Expr { + data: ExprKind::Var(x.name.clone()), + range: x.range, + })) + }); + + Box::new(Expr { + data: ExprKind::Constr(sum_type.name.clone(), args.to_vec()), + range: sum_type.name.range, + }) + }); + + let data_constructor = Entry { + name: cons_ident.clone(), + args: irrelevant_params.extend(&pre_indices).extend(&cons.args), + typ, + rules: Vec::new(), + attrs: Vec::new(), + docs: vec![], + range: cons_ident.range, + }; + + let book_info = cons.extract_book_info(&sum_type); + book.insert(cons_ident.to_string(), (data_constructor, book_info)); + } +} + pub fn expand_book(book: &mut Book) { - let mut entries = HashMap::new(); - for entry in book.entries.values_mut() { + let mut entries = FxHashMap::default(); + for entry in book.entries.values() { match entry { TopLevel::SumType(sum) => { let res = derive_match(sum.name.range, sum); - entries.insert(res.name.to_string(), res); + let info = res.extract_book_info(); + entries.insert(res.name.to_string(), (res, info)); + } + TopLevel::RecordType(rec) => { + let res = derive_open(rec.name.range, rec); + let info = res.extract_book_info(); + entries.insert(res.name.to_string(), (res, info)); } - TopLevel::RecordType(_) => (), TopLevel::Entry(_) => (), } } - for (name, tl) in entries { - book.count.insert(name.clone(), tl.extract_book_info()); + for (name, (tl, count)) in entries { + book.count.insert(name.clone(), count); book.names.insert(name.clone().to_string(), tl.name.clone()); book.entries.insert(name.clone(), TopLevel::Entry(tl)); } diff --git a/src/kind-pass/src/unbound/mod.rs b/src/kind-pass/src/unbound/mod.rs index d186fcc1..d62efce3 100644 --- a/src/kind-pass/src/unbound/mod.rs +++ b/src/kind-pass/src/unbound/mod.rs @@ -113,6 +113,20 @@ impl Visitor for UnboundCollector { Some(res) => self.visit_expr(res), None => (), } + + if let Some(fst) = self + .context_vars + .iter() + .find(|x| x.1 == argument.name.to_string()) + { + self.errors + .send(PassError::RepeatedVariable(fst.0, argument.name.range).into()) + .unwrap() + } else { + self.context_vars + .push((argument.name.range, argument.name.to_string())) + } + self.context_vars .push((argument.name.range, argument.name.to_string())); } @@ -137,6 +151,7 @@ impl Visitor for UnboundCollector { } self.visit_expr(&mut entry.typ); + self.context_vars = vars; for rule in &mut entry.rules { @@ -317,7 +332,7 @@ impl Visitor for UnboundCollector { ExprKind::Constr(ident, spine) => { self.visit_qualified_ident(ident); visit_vec!(spine.iter_mut(), arg => self.visit_binding(arg)); - }, + } ExprKind::All(None, typ, body) => { self.visit_expr(typ); self.visit_expr(body); diff --git a/src/kind-target-hvm/src/lib.rs b/src/kind-target-hvm/src/lib.rs index 82b8126d..ac53ae8a 100644 --- a/src/kind-target-hvm/src/lib.rs +++ b/src/kind-target-hvm/src/lib.rs @@ -35,13 +35,13 @@ pub fn compile_term(expr: &desugared::Expr) -> Box { name: op.to_string(), args: vec![compile_term(l), compile_term(r)], }), - Typ => unreachable!("Internal Error: 'Typ' cannot be a relevant term"), - U60 => unreachable!("Internal Error: 'U60' cannot be a relevant term"), - Str(_) => unreachable!("Internal Error: 'Str' cannot be a relevant term"), Hole(_) => unreachable!("Internal Error: 'Hole' cannot be a relevant term"), + | Typ => unreachable!("Internal Error: 'Typ' cannot be a relevant term"), + | U60 => unreachable!("Internal Error: 'U60' cannot be a relevant term"), + | All(_, _, _) => unreachable!("Internal Error: 'All' cannot be a relevant term"), + Str(_) => unreachable!("Internal Error: 'Str' cannot be a relevant term"), Hlp(_) => unreachable!("Internal Error: 'Hlp' cannot be a relevant term"), Err => unreachable!("Internal Error: 'Err' cannot be a relevant term"), - All(_, _, _) => unreachable!("Internal Error: 'All' cannot be a relevant term"), } } diff --git a/src/kind-tree/src/concrete/mod.rs b/src/kind-tree/src/concrete/mod.rs index 7f803e98..7fb08778 100644 --- a/src/kind-tree/src/concrete/mod.rs +++ b/src/kind-tree/src/concrete/mod.rs @@ -252,7 +252,7 @@ impl Display for TopLevel { } writeln!(f, " {{")?; for cons in &sum.constructors { - writeln!(f, " {},", cons)?; + writeln!(f, " {}", cons)?; } writeln!(f, "}}\n") } @@ -592,7 +592,7 @@ impl Entry { hiddens, erased, arguments, - is_ctr: false, + is_ctr: self.rules.len() == 0, range: self.name.range, } } From 64187026dae7c608560560f0526df5d2c6ed6847 Mon Sep 17 00:00:00 2001 From: Felipe g Date: Wed, 9 Nov 2022 13:40:56 -0300 Subject: [PATCH 6/9] fix: type declarations --- src/kind-driver/src/lib.rs | 1 - src/kind-parser/src/top_level/mod.rs | 10 ++-- src/kind-pass/src/desugar/top_level.rs | 20 +++++++- src/kind-pass/src/erasure/mod.rs | 33 +++++++------ src/kind-pass/src/errors.rs | 64 +++++++++++++++++++++++++- 5 files changed, 103 insertions(+), 25 deletions(-) diff --git a/src/kind-driver/src/lib.rs b/src/kind-driver/src/lib.rs index fc31328d..a6f12ec4 100644 --- a/src/kind-driver/src/lib.rs +++ b/src/kind-driver/src/lib.rs @@ -56,7 +56,6 @@ pub fn erase_book(session: &mut Session, path: &PathBuf) -> Option Option { let concrete_book = to_book(session, path)?; let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?; diff --git a/src/kind-parser/src/top_level/mod.rs b/src/kind-parser/src/top_level/mod.rs index ff5c5492..9720a3f8 100644 --- a/src/kind-parser/src/top_level/mod.rs +++ b/src/kind-parser/src/top_level/mod.rs @@ -150,14 +150,12 @@ impl<'a> Parser<'a> { let args = self.parse_arguments()?; + self.eat_variant(Token::Colon)?; + let typ = self.parse_expr(false)?; + if self.check_actual(Token::LBrace) { let start = self.range(); - let typ = Box::new(Expr { - data: ExprKind::Hole, - range: ident.range, - }); - self.eat_variant(Token::LBrace)?; let body = self.parse_expr(true)?; @@ -200,8 +198,6 @@ impl<'a> Parser<'a> { range: start.mix(end), }) } else { - self.eat_variant(Token::Colon)?; - let typ = self.parse_expr(false)?; let mut rules = Vec::new(); loop { let res = self.try_single(&|parser| parser.parse_rule(ident.to_string()))?; diff --git a/src/kind-pass/src/desugar/top_level.rs b/src/kind-pass/src/desugar/top_level.rs index 23e9c6c0..71e8499d 100644 --- a/src/kind-pass/src/desugar/top_level.rs +++ b/src/kind-pass/src/desugar/top_level.rs @@ -1,6 +1,6 @@ use kind_span::{Range, Span}; use kind_tree::concrete::{self, Telescope}; -use kind_tree::desugared; +use kind_tree::desugared::{self, ExprKind}; use kind_tree::symbol::{QualifiedIdent}; use crate::errors::{PassError, Sugar}; @@ -82,7 +82,23 @@ impl<'a> DesugarState<'a> { }; let typ = match cons.typ.clone() { - Some(expr) => self.desugar_expr(&expr), + Some(expr) => { + let res = self.desugar_expr(&expr); + match &res.data { + ExprKind::Ctr(name, spine) if name.to_string() == sum_type.name.to_string() => { + for i in 0..sum_type.parameters.len() { + match &spine[i].data { + ExprKind::Var(name) if name.to_string() == sum_type.parameters[i].name.to_string() => (), + _ => { + self.send_err(PassError::ShouldBeAParameter(spine[i].span, sum_type.parameters[i].range)); + } + } + } + } + _ => self.send_err(PassError::NotATypeConstructor(expr.range, sum_type.name.range)) + } + res + }, None => { let args = [irrelevant_params.as_slice(), pre_indices] .concat() diff --git a/src/kind-pass/src/erasure/mod.rs b/src/kind-pass/src/erasure/mod.rs index 019df77f..f910f209 100644 --- a/src/kind-pass/src/erasure/mod.rs +++ b/src/kind-pass/src/erasure/mod.rs @@ -255,15 +255,18 @@ impl<'a> ErasureState<'a> { match &expr.data { Typ | U60 | Num(_) | Str(_) | Err => Box::new(expr.clone()), - Hole(_) | Hlp(_) => { - match &expr.span { - kind_span::Span::Generated => Box::new(expr.clone()), - kind_span::Span::Locatable(span) => { - if !self.unify(span.clone(), on.clone(), (None, Relevance::Irrelevant), false) { - self.err_irrelevant(None, span.clone(), None) - } - Box::new(expr.clone()) - }, + Hole(_) | Hlp(_) => match &expr.span { + kind_span::Span::Generated => Box::new(expr.clone()), + kind_span::Span::Locatable(span) => { + if !self.unify( + span.clone(), + on.clone(), + (None, Relevance::Irrelevant), + false, + ) { + self.err_irrelevant(None, span.clone(), None) + } + Box::new(expr.clone()) } }, Var(name) => { @@ -375,13 +378,17 @@ impl<'a> ErasureState<'a> { self.err_irrelevant(None, head.range, None) } - let spine = spine.iter().zip(args).map(|(expr, arg)| { - self.erase_expr(&(Some(arg.span), erasure_to_relevance(arg.erased)), expr) - }); + let spine = spine + .iter() + .zip(args) + .map(|(expr, arg)| { + (self.erase_expr(&(Some(arg.span), erasure_to_relevance(arg.erased)), expr), arg) + }) + .filter(|(_, arg)| !arg.erased); Box::new(Expr { span: expr.span, - data: ExprKind::Ctr(head.clone(), spine.collect()), + data: ExprKind::Ctr(head.clone(), spine.map(|(expr, _)| expr).collect()), }) } Ann(relev, irrel) => { diff --git a/src/kind-pass/src/errors.rs b/src/kind-pass/src/errors.rs index dcfef199..667852cb 100644 --- a/src/kind-pass/src/errors.rs +++ b/src/kind-pass/src/errors.rs @@ -1,5 +1,5 @@ use kind_report::data::{Color, DiagnosticFrame, Marker, Severity}; -use kind_span::Range; +use kind_span::{Range, Span}; pub enum Sugar { DoNotation, @@ -26,7 +26,9 @@ pub enum PassError { RulesWithInconsistentArity(Vec<(Range, usize)>), SugarIsBadlyImplemented(Range, Range, usize), CannotUseIrrelevant(Option, Range, Option), - CannotFindAlias(String, Range) + CannotFindAlias(String, Range), + NotATypeConstructor(Range, Range), + ShouldBeAParameter(Span, Range), } // TODO: A way to build an error message with methods @@ -353,6 +355,64 @@ impl From for DiagnosticFrame { } ], }, + PassError::ShouldBeAParameter(error_range, declaration_range) => { + let mut positions = vec![]; + + match error_range { + Span::Generated => (), + Span::Locatable(error_range) => { + positions.push(Marker { + position: error_range, + color: Color::Fst, + text: format!("This expression is not the parameter"), + no_code: false, + main: true, + }) + }, + } + + positions.push( + Marker { + position: declaration_range, + color: Color::Snd, + text: format!("This is the parameter that should be used"), + no_code: false, + main: false, + } + ); + + DiagnosticFrame { + code: 214, + severity: Severity::Error, + title: "The expression is not the parameter declared in the type constructor".to_string(), + subtitles: vec![], + hints: vec![], + positions + } + } + PassError::NotATypeConstructor(error_range, declaration_range) => DiagnosticFrame { + code: 214, + severity: Severity::Error, + title: "This is not the type that is being declared.".to_string(), + subtitles: vec![], + hints: vec![], + positions: vec![ + Marker { + position: error_range, + color: Color::Fst, + text: format!("This is not the type that is being declared"), + no_code: false, + main: true, + }, + Marker { + position: declaration_range, + color: Color::Snd, + text: format!("This is the type that should be used instead"), + no_code: false, + main: false, + } + ], + }, } } } From 3dfc967327e31cf625d89d8f3efae61bb019c443 Mon Sep 17 00:00:00 2001 From: Felipe g Date: Wed, 9 Nov 2022 13:56:01 -0300 Subject: [PATCH 7/9] style: format and fix clippy sugestions --- Cargo.lock | 1325 +++++++++++++++++++++++- src/kind-checker/src/compiler/mod.rs | 2 +- src/kind-checker/src/lib.rs | 4 +- src/kind-checker/src/report.rs | 27 +- src/kind-cli/src/main.rs | 30 +- src/kind-derive/src/matching.rs | 38 +- src/kind-derive/src/open.rs | 19 +- src/kind-driver/src/lib.rs | 13 +- src/kind-driver/src/resolution.rs | 21 +- src/kind-parser/src/errors.rs | 2 +- src/kind-parser/src/expr.rs | 9 +- src/kind-parser/src/lexer/literals.rs | 4 +- src/kind-parser/src/lexer/mod.rs | 4 +- src/kind-parser/src/top_level/mod.rs | 32 +- src/kind-pass/src/desugar/destruct.rs | 2 +- src/kind-pass/src/desugar/expr.rs | 2 +- src/kind-pass/src/desugar/top_level.rs | 30 +- src/kind-pass/src/erasure/mod.rs | 48 +- src/kind-pass/src/errors.rs | 8 +- src/kind-pass/src/expand/mod.rs | 19 +- src/kind-pass/src/expand/uses.rs | 17 +- src/kind-pass/src/unbound/mod.rs | 14 +- src/kind-report/src/lib.rs | 2 +- src/kind-report/src/report.rs | 15 +- src/kind-target-hvm/src/lib.rs | 12 +- src/kind-tree/src/concrete/mod.rs | 10 +- src/kind-tree/src/concrete/visitor.rs | 2 +- src/kind-tree/src/symbol.rs | 2 +- 28 files changed, 1537 insertions(+), 176 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f7b3169a..0d757cb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +dependencies = [ + "memchr", +] + [[package]] name = "atty" version = "0.2.14" @@ -13,18 +22,80 @@ dependencies = [ "winapi", ] +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + +[[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" + [[package]] name = "byteorder" version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "3.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" +dependencies = [ + "atty", + "bitflags", + "clap_derive 3.2.18", + "clap_lex 0.2.4", + "indexmap", + "once_cell", + "strsim", + "termcolor", + "textwrap", +] + [[package]] name = "clap" version = "4.0.15" @@ -33,13 +104,26 @@ checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f" dependencies = [ "atty", "bitflags", - "clap_derive", - "clap_lex", + "clap_derive 4.0.13", + "clap_lex 0.3.0", "once_cell", "strsim", "termcolor", ] +[[package]] +name = "clap_derive" +version = "3.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "clap_derive" version = "4.0.13" @@ -53,6 +137,15 @@ dependencies = [ "syn", ] +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "clap_lex" version = "0.3.0" @@ -62,6 +155,187 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "dashmap" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + +[[package]] +name = "encoding_rs" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "eyre" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + +[[package]] +name = "filetime" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "windows-sys 0.42.0", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[package]] +name = "futures-channel" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" + +[[package]] +name = "futures-io" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" + +[[package]] +name = "futures-sink" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" + +[[package]] +name = "futures-task" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" + +[[package]] +name = "futures-util" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +dependencies = [ + "futures-core", + "futures-io", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + [[package]] name = "fxhash" version = "0.2.1" @@ -71,6 +345,31 @@ dependencies = [ "byteorder", ] +[[package]] +name = "h2" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "heck" version = "0.4.0" @@ -86,15 +385,220 @@ dependencies = [ "libc", ] +[[package]] +name = "highlight_error" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e18805660d7b6b2e2b9f316a5099521b5998d5cba4dda11b5157a21aaef03" + +[[package]] +name = "http" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hvm" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0581f8e42136b54e77d3180b6c871486ad2a2dca5e394daaa38fa3190dd00c9" +dependencies = [ + "clap 3.2.22", + "highlight_error", + "instant", + "itertools", + "num_cpus", + "regex", + "reqwest", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "hyper" +version = "0.14.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "im" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" +dependencies = [ + "bitmaps", + "rand_core", + "rand_xoshiro", + "sized-chunks", + "typenum", + "version_check", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "indexmap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "ipnet" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" + +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "kind-checker" version = "0.1.0" +dependencies = [ + "fxhash", + "hvm", + "im", + "kind-report", + "kind-span", + "kind-tree", +] [[package]] name = "kind-cli" version = "0.3.0" dependencies = [ - "clap", + "clap 4.0.15", + "kind-checker", "kind-driver", "kind-report", ] @@ -102,22 +606,36 @@ dependencies = [ [[package]] name = "kind-derive" version = "0.1.0" - -[[package]] -name = "kind-driver" -version = "0.1.0" dependencies = [ - "kind-parser", - "kind-pass", "kind-report", "kind-span", "kind-tree", ] +[[package]] +name = "kind-driver" +version = "0.1.0" +dependencies = [ + "dashmap", + "eyre", + "fxhash", + "hvm", + "kind-checker", + "kind-parser", + "kind-pass", + "kind-report", + "kind-span", + "kind-target-hvm", + "kind-tree", + "notify-debouncer-mini", + "strsim", +] + [[package]] name = "kind-parser" version = "0.1.0" dependencies = [ + "fxhash", "kind-report", "kind-span", "kind-tree", @@ -127,15 +645,20 @@ dependencies = [ name = "kind-pass" version = "0.1.0" dependencies = [ + "fxhash", + "im", + "kind-derive", "kind-report", "kind-span", "kind-tree", + "linked-hash-map", ] [[package]] name = "kind-report" version = "0.1.0" dependencies = [ + "fxhash", "kind-span", "unicode-width", "yansi", @@ -148,6 +671,12 @@ version = "0.1.0" [[package]] name = "kind-target-hvm" version = "0.1.0" +dependencies = [ + "kind-derive", + "kind-report", + "kind-span", + "kind-tree", +] [[package]] name = "kind-target-kdl" @@ -158,27 +687,242 @@ name = "kind-tree" version = "0.1.0" dependencies = [ "fxhash", + "hvm", "kind-span", + "linked-hash-map", ] +[[package]] +name = "kqueue" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" +dependencies = [ + "bitflags", + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.135" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mio" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.36.1", +] + +[[package]] +name = "native-tls" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "notify" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2c66da08abae1c024c01d635253e402341b4060a12e99b31c7594063bf490a" +dependencies = [ + "bitflags", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "mio", + "walkdir", + "winapi", +] + +[[package]] +name = "notify-debouncer-mini" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e23e9fa24f094b143c1eb61f90ac6457de87be6987bc70746e0179f7dbc9007b" +dependencies = [ + "crossbeam-channel", + "notify", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "once_cell" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" +[[package]] +name = "openssl" +version = "0.10.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5230151e44c0f05157effb743e8d517472843121cf9243e8b81393edb5acd9ce" +dependencies = [ + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "os_str_bytes" version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" +[[package]] +name = "parking_lot_core" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys 0.42.0", +] + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -221,6 +965,211 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" + +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "reqwest" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "ryu" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +dependencies = [ + "lazy_static", + "windows-sys 0.36.1", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "security-framework" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" + +[[package]] +name = "serde_json" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + +[[package]] +name = "slab" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "strsim" version = "0.10.0" @@ -238,6 +1187,20 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + [[package]] name = "termcolor" version = "1.1.3" @@ -247,24 +1210,259 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "textwrap" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" +dependencies = [ + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "winapi", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "unicode-bidi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + [[package]] name = "unicode-ident" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-width" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + +[[package]] +name = "web-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -296,6 +1494,115 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.0", + "windows_i686_gnu 0.42.0", + "windows_i686_msvc 0.42.0", + "windows_x86_64_gnu 0.42.0", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "yansi" version = "0.5.1" diff --git a/src/kind-checker/src/compiler/mod.rs b/src/kind-checker/src/compiler/mod.rs index 76fed940..e13452aa 100644 --- a/src/kind-checker/src/compiler/mod.rs +++ b/src/kind-checker/src/compiler/mod.rs @@ -80,7 +80,7 @@ fn mk_single_ctr(head: String) -> Box { fn mk_ctr_name(ident: &QualifiedIdent) -> Box { // Adds an empty segment (so it just appends a dot in the end) - mk_single_ctr(format!("{}.", ident.to_string())) + mk_single_ctr(format!("{}.", ident)) } fn span_to_num(span: Span) -> Box { diff --git a/src/kind-checker/src/lib.rs b/src/kind-checker/src/lib.rs index 8a92d010..1c211850 100644 --- a/src/kind-checker/src/lib.rs +++ b/src/kind-checker/src/lib.rs @@ -53,7 +53,5 @@ pub fn eval_api(book: &Book) -> Box { let main = runtime.alloc_code("Kind.API.eval_main").unwrap(); runtime.run_io(main); runtime.normalize(main); - let term = runtime.readback(main); - - term + runtime.readback(main) } diff --git a/src/kind-checker/src/report.rs b/src/kind-checker/src/report.rs index 0ee30716..50ec5041 100644 --- a/src/kind-checker/src/report.rs +++ b/src/kind-checker/src/report.rs @@ -55,25 +55,23 @@ fn parse_op(term: &Term) -> Result { fn parse_name(term: &Term) -> Result { match term { - Term::Num { numb } => { - Ok(Ident::decode(*numb)) - } - Term::Ctr { name, args: _ } => { - Ok(name.to_string()) - } - _ => Err("Error while matching opt".to_string()) + Term::Num { numb } => Ok(Ident::decode(*numb)), + Term::Ctr { name, args: _ } => Ok(name.to_string()), + _ => Err("Error while matching opt".to_string()), } } fn parse_qualified(term: &Term) -> Result { match term { - Term::Num { numb } => { - Ok(QualifiedIdent::new_static(&Ident::decode(*numb), None, Range::ghost_range())) - } + Term::Num { numb } => Ok(QualifiedIdent::new_static( + &Ident::decode(*numb), + None, + Range::ghost_range(), + )), Term::Ctr { name, args: _ } => { - Ok(QualifiedIdent::new_static(&name, None, Range::ghost_range())) + Ok(QualifiedIdent::new_static(name, None, Range::ghost_range())) } - _ => Err("Error while matching opt".to_string()) + _ => Err("Error while matching opt".to_string()), } } @@ -158,7 +156,10 @@ fn parse_all_expr( parse_all_expr(names.clone(), &args[2])?, parse_all_expr(names, &args[3])?, )), - tag => Err(format!("Unexpected tag on transforming quoted term {:?}", tag)), + tag => Err(format!( + "Unexpected tag on transforming quoted term {:?}", + tag + )), }, _ => Err("Unexpected term on transforming quoted term".to_string()), } diff --git a/src/kind-cli/src/main.rs b/src/kind-cli/src/main.rs index 24b887a5..fdd1039a 100644 --- a/src/kind-cli/src/main.rs +++ b/src/kind-cli/src/main.rs @@ -166,44 +166,52 @@ fn main() { Command::ToHVM { file } => { compile_in_session(render_config, root, file.clone(), &mut |session| { driver::compile_book_to_hvm(session, &PathBuf::from(file.clone())) - }).and_then(|res| { + }) + .map(|res| { println!("{}", res); - Some(res) + res }); } Command::Run { file } => { compile_in_session(render_config, root, file.clone(), &mut |session| { driver::compile_book_to_hvm(session, &PathBuf::from(file.clone())) - }).and_then(|res| { + }) + .map(|res| { println!("{}", driver::execute_file(&res)); - Some(res) + res }); } Command::Eval { file } => { compile_in_session(render_config, root, file.clone(), &mut |session| { driver::erase_book(session, &PathBuf::from(file.clone())) - }).and_then(|res| { + }) + .map(|res| { println!("{}", driver::eval_in_checker(&res)); - Some(res) + res }); } Command::Show { file } => { compile_in_session(render_config, root, file.clone(), &mut |session| { driver::to_book(session, &PathBuf::from(file.clone())) - }).and_then(|res| { + }) + .map(|res| { print!("{}", res); - Some(res) + res }); } Command::GenChecker { file } => { compile_in_session(render_config, root, file.clone(), &mut |session| { driver::check_erasure_book(session, &PathBuf::from(file.clone())) - }).and_then(|res| { + }) + .map(|res| { print!("{}", driver::generate_checker(&res)); - Some(res) + res }); } - Command::ToKDL { file: _, namespace: _ } => todo!(), + Command::ToKDL { + file: _, + namespace: _, + } => todo!(), Command::Watch { file: _ } => todo!(), Command::Repl => todo!(), } diff --git a/src/kind-derive/src/matching.rs b/src/kind-derive/src/matching.rs index a367e23c..b66da19e 100644 --- a/src/kind-derive/src/matching.rs +++ b/src/kind-derive/src/matching.rs @@ -56,7 +56,7 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { for arg in sum.indices.iter() { types.push(arg.to_implicit()) } - + // The type let all_args = sum.parameters.extend(&sum.indices); @@ -75,7 +75,6 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { .map(|x| Binding::Positional(mk_var(x.name.clone()))) .collect(); - let indice_names: Vec = sum .indices .iter() @@ -98,7 +97,13 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { let motive_type = sum.parameters.extend(&sum.indices).iter().rfold( mk_pi(Ident::new_static("_val", range), res_motive_ty, mk_typ()), - |out, arg| mk_pi(arg.name.clone(), arg.typ.clone().unwrap_or(mk_typ()), out), + |out, arg| { + mk_pi( + arg.name.clone(), + arg.typ.clone().unwrap_or_else(mk_typ), + out, + ) + }, ); types.push(Argument { @@ -109,7 +114,9 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { range, }); - let params = sum.parameters.map(|x| Binding::Positional(mk_var(x.name.clone()))); + let params = sum + .parameters + .map(|x| Binding::Positional(mk_var(x.name.clone()))); // Constructors type for cons in &sum.constructors { @@ -119,7 +126,10 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { .map(|x| Binding::Positional(mk_var(x.name.clone()))) .collect(); - let cons_inst = mk_cons(sum.name.add_segment(cons.name.to_str()), [params.as_slice(), vars.as_slice()].concat()); + let cons_inst = mk_cons( + sum.name.add_segment(cons.name.to_str()), + [params.as_slice(), vars.as_slice()].concat(), + ); let mut indices_of_cons = match cons.typ.clone().map(|x| x.data) { Some(ExprKind::Constr(_, spine)) => spine.to_vec(), @@ -133,7 +143,7 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { let cons_type = cons.args.iter().rfold(cons_tipo, |out, arg| { mk_pi( arg.name.clone(), - arg.typ.clone().unwrap_or_else(|| mk_typ()), + arg.typ.clone().unwrap_or_else(mk_typ), out, ) }); @@ -157,12 +167,14 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { let cons_ident = sum.name.add_segment(cons.name.to_str()); let mut pats: Vec> = Vec::new(); - let spine_params: Vec = sum.parameters.extend(&cons.args) + let spine_params: Vec = sum + .parameters + .extend(&cons.args) .map(|x| x.name.with_name(|f| format!("{}_", f))) .to_vec(); - - let spine: Vec = cons.args + let spine: Vec = cons + .args .map(|x| x.name.with_name(|f| format!("{}_", f))) .to_vec(); @@ -201,7 +213,7 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { .iter() .map(|arg| Binding::Positional(mk_var(arg.clone()))) .collect(), - cons.name.range + cons.name.range, ); rules.push(Box::new(Rule { @@ -213,7 +225,7 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { } // Rules - let entry = Entry { + Entry { name, docs: Vec::new(), args: types, @@ -221,7 +233,5 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { rules, range, attrs: Vec::new(), - }; - - entry + } } diff --git a/src/kind-derive/src/open.rs b/src/kind-derive/src/open.rs index 0e2f0890..a051bbb2 100644 --- a/src/kind-derive/src/open.rs +++ b/src/kind-derive/src/open.rs @@ -67,11 +67,7 @@ pub fn derive_open(range: Range, sum: &RecordDecl) -> concrete::Entry { let cons_tipo = mk_var(Ident::generate("_res")); let cons_type = sum.fields.iter().rfold(cons_tipo, |out, (name, _, typ)| { - mk_pi( - name.clone(), - typ.clone(), - out, - ) + mk_pi(name.clone(), typ.clone(), out) }); // Sccrutinzies @@ -80,7 +76,7 @@ pub fn derive_open(range: Range, sum: &RecordDecl) -> concrete::Entry { hidden: false, erased: false, name: Ident::generate("scrutinizer"), - typ: Some(res_motive_ty.clone()), + typ: Some(res_motive_ty), range, }); @@ -106,7 +102,7 @@ pub fn derive_open(range: Range, sum: &RecordDecl) -> concrete::Entry { pats.push(Box::new(Pat { data: concrete::pat::PatKind::App( - sum.name.add_segment(sum.constructor.to_str()).clone(), + sum.name.add_segment(sum.constructor.to_str()), spine .iter() .cloned() @@ -134,9 +130,12 @@ pub fn derive_open(range: Range, sum: &RecordDecl) -> concrete::Entry { .collect(), ); - let rules = vec![ - Box::new(Rule { name: name.clone(), pats, body, range }) - ]; + let rules = vec![Box::new(Rule { + name: name.clone(), + pats, + body, + range, + })]; Entry { name, diff --git a/src/kind-driver/src/lib.rs b/src/kind-driver/src/lib.rs index a6f12ec4..a9528c24 100644 --- a/src/kind-driver/src/lib.rs +++ b/src/kind-driver/src/lib.rs @@ -1,10 +1,10 @@ -use kind_pass::{expand, desugar, erasure}; +use kind_pass::{desugar, erasure, expand}; use kind_report::report::FileCache; use kind_span::SyntaxCtxIndex; -use kind_tree::{desugared, backend, concrete}; +use kind_tree::{backend, concrete, desugared}; use session::Session; -use std::{path::PathBuf, collections::HashSet}; +use std::{collections::HashSet, path::PathBuf}; use kind_checker as checker; @@ -38,7 +38,7 @@ pub fn type_check_book(session: &mut Session, path: &PathBuf) -> Option Option { +pub fn to_book(session: &mut Session, path: &PathBuf) -> Option { let mut concrete_book = resolution::parse_and_store_book(session, path)?; expand::expand_book(&mut concrete_book); @@ -77,8 +77,7 @@ pub fn execute_file(file: &backend::File) -> Box { let main = runtime.alloc_code("Main").unwrap(); runtime.run_io(main); runtime.normalize(main); - let term = runtime.readback(main); - term + runtime.readback(main) } pub fn eval_in_checker(book: &desugared::Book) -> Box { @@ -89,4 +88,4 @@ pub fn eval_in_checker(book: &desugared::Book) -> Box { pub fn generate_checker(book: &desugared::Book) -> String { // TODO: Change to from_file when hvm support it checker::gen_checker(book) -} \ No newline at end of file +} diff --git a/src/kind-driver/src/resolution.rs b/src/kind-driver/src/resolution.rs index 2a4db8b6..e98e2e55 100644 --- a/src/kind-driver/src/resolution.rs +++ b/src/kind-driver/src/resolution.rs @@ -3,12 +3,12 @@ //! it returns a desugared book of all of the //! depedencies. +use fxhash::FxHashMap; +use kind_pass::expand::uses::expand_uses; use std::collections::HashSet; use std::fs; use std::path::{Path, PathBuf}; use std::rc::Rc; -use fxhash::FxHashMap; -use kind_pass::expand::uses::expand_uses; use strsim::jaro; use kind_pass::unbound::{self}; @@ -142,7 +142,7 @@ fn parse_and_store_book_by_identifier<'a>( session: &mut Session, ident: &QualifiedIdent, book: &'a mut Book, - unbound: &mut FxHashMap> + unbound: &mut FxHashMap>, ) -> bool { if book.entries.contains_key(ident.to_string().as_str()) { return false; @@ -162,7 +162,7 @@ fn parse_and_store_book_by_path<'a>( session: &mut Session, path: &PathBuf, book: &'a mut Book, - unbound: &mut FxHashMap> + unbound: &mut FxHashMap>, ) -> bool { if session.loaded_paths_map.contains_key(path) { return false; @@ -189,7 +189,7 @@ fn parse_and_store_book_by_path<'a>( unbound::get_module_unbound(session.diagnostic_sender.clone(), &mut module); for idents in unbound_vars.values() { - unbound_variable(session, &book, idents); + unbound_variable(session, book, idents); failed = true; } @@ -235,7 +235,14 @@ pub fn parse_and_store_book(session: &mut Session, path: &PathBuf) -> Option>().as_slice()) + unbound_variable( + session, + &book, + res.iter() + .map(|x| x.to_ident()) + .collect::>() + .as_slice(), + ) } if failed { @@ -243,4 +250,4 @@ pub fn parse_and_store_book(session: &mut Session, path: &PathBuf) -> Option &'static str { diff --git a/src/kind-parser/src/expr.rs b/src/kind-parser/src/expr.rs index b2680746..0fcf72f2 100644 --- a/src/kind-parser/src/expr.rs +++ b/src/kind-parser/src/expr.rs @@ -128,7 +128,7 @@ impl<'a> Parser<'a> { let range = self.range(); let (start, end) = eat_single!(self, Token::UpperId(start, end) => (start.clone(), end.clone()))?; - let ident = QualifiedIdent::new_static(start.as_str(), end.clone(), range); + let ident = QualifiedIdent::new_static(start.as_str(), end, range); Ok(ident) } @@ -217,7 +217,10 @@ impl<'a> Parser<'a> { "U60" => ExprKind::Lit(Literal::U60), _ => ExprKind::Constr(id.clone(), vec![]), }; - Ok(Box::new(Expr { range: id.range, data })) + Ok(Box::new(Expr { + range: id.range, + data, + })) } fn parse_data(&mut self, multiline: bool) -> Result, SyntaxError> { @@ -229,7 +232,7 @@ impl<'a> Parser<'a> { _ => { let (range_end, spine) = self.parse_call_tail(id.range, multiline)?; range = range_end; - ExprKind::Constr(id.clone(), spine) + ExprKind::Constr(id, spine) } }; Ok(Box::new(Expr { range, data })) diff --git a/src/kind-parser/src/lexer/literals.rs b/src/kind-parser/src/lexer/literals.rs index cae397c4..2705e8af 100644 --- a/src/kind-parser/src/lexer/literals.rs +++ b/src/kind-parser/src/lexer/literals.rs @@ -58,7 +58,7 @@ impl<'a> Lexer<'a> { fn lex_digit(&mut self, start: usize) -> (Token, Range) { let num = self.accumulate_while(&|x| x.is_ascii_digit() || x == '_'); ( - Token::Num(num.replace("_", "").parse::().unwrap()), + Token::Num(num.replace('_', "").parse::().unwrap()), self.mk_range(start), ) } @@ -68,7 +68,7 @@ impl<'a> Lexer<'a> { fn lex_base(&mut self, start: usize, base: u32, err: EncodeSequence) -> (Token, Range) { self.next_char(); let num = self.accumulate_while(&|x| x.is_digit(base) || x == '_'); - if let Ok(res) = u64::from_str_radix(&num.replace("_", ""), base) { + if let Ok(res) = u64::from_str_radix(&num.replace('_', ""), base) { (Token::Num(res), self.mk_range(start)) } else { ( diff --git a/src/kind-parser/src/lexer/mod.rs b/src/kind-parser/src/lexer/mod.rs index 33bffb81..7b1482e7 100644 --- a/src/kind-parser/src/lexer/mod.rs +++ b/src/kind-parser/src/lexer/mod.rs @@ -104,7 +104,7 @@ impl<'a> Lexer<'a> { } } c if c.is_ascii_digit() => self.lex_number(), - c if is_valid_upper_start(*c).clone() => { + c if is_valid_upper_start(*c) => { let first_part = self.accumulate_while(&is_valid_id).to_string(); let peek = self.peekable.peek().cloned(); let auxiliar_part = match peek { @@ -116,7 +116,7 @@ impl<'a> Lexer<'a> { _ => None, }; ( - Token::UpperId(first_part.to_string(), auxiliar_part), + Token::UpperId(first_part, auxiliar_part), self.mk_range(start), ) } diff --git a/src/kind-parser/src/top_level/mod.rs b/src/kind-parser/src/top_level/mod.rs index 9720a3f8..9277cc1a 100644 --- a/src/kind-parser/src/top_level/mod.rs +++ b/src/kind-parser/src/top_level/mod.rs @@ -1,9 +1,8 @@ use fxhash::FxHashMap; -use kind_tree::concrete::expr::Expr; -use kind_tree::concrete::pat::{PatIdent, Pat, PatKind}; +use kind_tree::concrete::pat::{Pat, PatIdent, PatKind}; /// Parses all of the top level structures /// like Book, Entry, Rule and Argument. -use kind_tree::concrete::{Argument, Attribute, Entry, Module, Rule, Telescope, TopLevel, ExprKind}; +use kind_tree::concrete::{Argument, Attribute, Entry, Module, Rule, Telescope, TopLevel}; use kind_tree::symbol::QualifiedIdent; use crate::errors::SyntaxError; @@ -163,17 +162,20 @@ impl<'a> Parser<'a> { let end = self.range(); self.eat_closing_keyword(Token::RBrace, start)?; - let mut rules = vec![ - Box::new(Rule { - name: ident.clone(), - pats: args.iter().map(|x| Box::new(Pat { - range: x.range, - data: PatKind::Var(PatIdent(x.name.clone())), - })).collect(), - body, - range: end, - }) - ]; + let mut rules = vec![Box::new(Rule { + name: ident.clone(), + pats: args + .iter() + .map(|x| { + Box::new(Pat { + range: x.range, + data: PatKind::Var(PatIdent(x.name.clone())), + }) + }) + .collect(), + body, + range: end, + })]; loop { let res = self.try_single(&|parser| parser.parse_rule(ident.to_string()))?; match res { @@ -185,7 +187,7 @@ impl<'a> Parser<'a> { // Better error message when you have change the name of the function if self.get().is_upper_id() && !self.is_top_level_entry_continuation() { - return Err(SyntaxError::NotAClauseOfDef(ident.range.clone(), self.range())); + return Err(SyntaxError::NotAClauseOfDef(ident.range, self.range())); } Ok(Entry { diff --git a/src/kind-pass/src/desugar/destruct.rs b/src/kind-pass/src/desugar/destruct.rs index 48d5f18d..7fb6d2fe 100644 --- a/src/kind-pass/src/desugar/destruct.rs +++ b/src/kind-pass/src/desugar/destruct.rs @@ -52,7 +52,7 @@ impl<'a> DesugarState<'a> { .collect(); if !jump_rest && !names.is_empty() { - self.send_err(PassError::NoCoverage(type_info.0.clone(), names)) + self.send_err(PassError::NoCoverage(*type_info.0, names)) } ordered_fields diff --git a/src/kind-pass/src/desugar/expr.rs b/src/kind-pass/src/desugar/expr.rs index 51d7e637..6143db43 100644 --- a/src/kind-pass/src/desugar/expr.rs +++ b/src/kind-pass/src/desugar/expr.rs @@ -51,7 +51,7 @@ impl<'a> DesugarState<'a> { range, bind_ident.clone(), vec![expr, desugared::Expr::lambda(range, name, next)], - false + false, ) }; diff --git a/src/kind-pass/src/desugar/top_level.rs b/src/kind-pass/src/desugar/top_level.rs index 71e8499d..b863e5d7 100644 --- a/src/kind-pass/src/desugar/top_level.rs +++ b/src/kind-pass/src/desugar/top_level.rs @@ -1,7 +1,7 @@ use kind_span::{Range, Span}; use kind_tree::concrete::{self, Telescope}; use kind_tree::desugared::{self, ExprKind}; -use kind_tree::symbol::{QualifiedIdent}; +use kind_tree::symbol::QualifiedIdent; use crate::errors::{PassError, Sugar}; @@ -85,20 +85,29 @@ impl<'a> DesugarState<'a> { Some(expr) => { let res = self.desugar_expr(&expr); match &res.data { - ExprKind::Ctr(name, spine) if name.to_string() == sum_type.name.to_string() => { - for i in 0..sum_type.parameters.len() { + ExprKind::Ctr(name, spine) + if name.to_string() == sum_type.name.to_string() => + { + for (i, parameter) in sum_type.parameters.iter().enumerate() { match &spine[i].data { - ExprKind::Var(name) if name.to_string() == sum_type.parameters[i].name.to_string() => (), + ExprKind::Var(name) + if name.to_string() == parameter.name.to_string() => {} _ => { - self.send_err(PassError::ShouldBeAParameter(spine[i].span, sum_type.parameters[i].range)); + self.send_err(PassError::ShouldBeAParameter( + spine[i].span, + parameter.range, + )); } } } } - _ => self.send_err(PassError::NotATypeConstructor(expr.range, sum_type.name.range)) + _ => self.send_err(PassError::NotATypeConstructor( + expr.range, + sum_type.name.range, + )), } res - }, + } None => { let args = [irrelevant_params.as_slice(), pre_indices] .concat() @@ -124,7 +133,6 @@ impl<'a> DesugarState<'a> { span: Span::Locatable(cons.name.range), }; - self.new_book .entrs .insert(cons_ident.to_string(), Box::new(data_constructor)); @@ -204,8 +212,7 @@ impl<'a> DesugarState<'a> { fst: &concrete::pat::Pat, snd: &concrete::pat::Pat, ) -> Box { - let sigma_new = - QualifiedIdent::new_static("Sigma", Some("new".to_string()), range); + let sigma_new = QualifiedIdent::new_static("Sigma", Some("new".to_string()), range); let entry = self.old_book.entries.get(sigma_new.to_string().as_str()); if entry.is_none() { @@ -296,7 +303,7 @@ impl<'a> DesugarState<'a> { concrete::pat::PatKind::Hole => { let name = self.gen_name(pat.range); desugared::Expr::var(name) - }, + } concrete::pat::PatKind::Var(ident) => desugared::Expr::var(ident.0.clone()), concrete::pat::PatKind::Num(n) => desugared::Expr::num(pat.range, *n), concrete::pat::PatKind::Pair(fst, snd) => self.desugar_pair_pat(pat.range, fst, snd), @@ -361,7 +368,6 @@ impl<'a> DesugarState<'a> { } pub fn desugar_entry(&mut self, entry: &concrete::Entry) { - self.name_count = 0; let rules = entry diff --git a/src/kind-pass/src/erasure/mod.rs b/src/kind-pass/src/erasure/mod.rs index f910f209..16ea374d 100644 --- a/src/kind-pass/src/erasure/mod.rs +++ b/src/kind-pass/src/erasure/mod.rs @@ -60,8 +60,9 @@ pub fn erase_book( for name in entrypoint { let count = state.holes.len(); - let ty = (None, Relevance::Hole(count)); - state.names.insert(name.to_string(), ty.clone()); + state + .names + .insert(name.to_string(), (None, Relevance::Hole(count))); state.holes.push(Some(Relevance::Relevant)); } @@ -95,10 +96,10 @@ pub fn erasure_to_relevance(erased: bool) -> Relevance { impl<'a> ErasureState<'a> { pub fn new_hole(&mut self, range: Range, name: String) -> (Option, Relevance) { let count = self.holes.len(); - let ty = (Some(range), Relevance::Hole(count)); - self.names.insert(name.to_string(), ty.clone()); + let local_relevance = (Some(range), Relevance::Hole(count)); + self.names.insert(name, local_relevance); self.holes.push(None); - ty + local_relevance } pub fn err_irrelevant( @@ -220,7 +221,7 @@ impl<'a> ErasureState<'a> { } Fun(name, spine) | Ctr(name, spine) => { let fun = match self.names.get(&name.to_string()) { - Some(res) => res.clone(), + Some(res) => *res, None => self.new_hole(name.range, name.to_string()), }; @@ -258,13 +259,8 @@ impl<'a> ErasureState<'a> { Hole(_) | Hlp(_) => match &expr.span { kind_span::Span::Generated => Box::new(expr.clone()), kind_span::Span::Locatable(span) => { - if !self.unify( - span.clone(), - on.clone(), - (None, Relevance::Irrelevant), - false, - ) { - self.err_irrelevant(None, span.clone(), None) + if !self.unify(*span, *on, (None, Relevance::Irrelevant), false) { + self.err_irrelevant(None, *span, None) } Box::new(expr.clone()) } @@ -273,7 +269,7 @@ impl<'a> ErasureState<'a> { let relev = self.ctx.get(&name.to_string()).unwrap(); let declared_ty = (relev.1).0; let declared_val = relev.0; - if !self.unify(name.range, on.clone(), relev.1, false) { + if !self.unify(name.range, *on, relev.1, false) { self.err_irrelevant(Some(declared_val), name.range, declared_ty) } Box::new(expr.clone()) @@ -282,7 +278,7 @@ impl<'a> ErasureState<'a> { let ctx = self.ctx.clone(); // Relevant inside the context that is it's being used? - self.ctx.insert(name.to_string(), (name.range, on.clone())); + self.ctx.insert(name.to_string(), (name.range, *on)); self.erase_expr(&(on.0, Relevance::Irrelevant), typ); self.erase_expr(&(on.0, Relevance::Irrelevant), body); @@ -292,7 +288,7 @@ impl<'a> ErasureState<'a> { } Lambda(name, body) => { let ctx = self.ctx.clone(); - self.ctx.insert(name.to_string(), (name.range, on.clone())); + self.ctx.insert(name.to_string(), (name.range, *on)); let body = self.erase_expr(on, body); self.ctx = ctx; @@ -303,7 +299,7 @@ impl<'a> ErasureState<'a> { } Let(name, val, body) => { let ctx = self.ctx.clone(); - self.ctx.insert(name.to_string(), (name.range, on.clone())); + self.ctx.insert(name.to_string(), (name.range, *on)); let val = self.erase_expr(on, val); let body = self.erase_expr(on, body); @@ -333,11 +329,11 @@ impl<'a> ErasureState<'a> { .iter(); let fun = match self.names.get(&head.to_string()) { - Some(res) => res.clone(), + Some(res) => *res, None => self.new_hole(head.range, head.to_string()), }; - if !self.unify(head.range, on.clone(), fun, true) { + if !self.unify(head.range, *on, fun, true) { self.err_irrelevant(None, head.range, None) } @@ -370,11 +366,11 @@ impl<'a> ErasureState<'a> { .iter(); let fun = match self.names.get(&head.to_string()) { - Some(res) => res.clone(), + Some(res) => *res, None => self.new_hole(head.range, head.to_string()), }; - if !self.unify(head.range, on.clone(), fun, true) { + if !self.unify(head.range, *on, fun, true) { self.err_irrelevant(None, head.range, None) } @@ -382,7 +378,13 @@ impl<'a> ErasureState<'a> { .iter() .zip(args) .map(|(expr, arg)| { - (self.erase_expr(&(Some(arg.span), erasure_to_relevance(arg.erased)), expr), arg) + ( + self.erase_expr( + &(Some(arg.span), erasure_to_relevance(arg.erased)), + expr, + ), + arg, + ) }) .filter(|(_, arg)| !arg.erased); @@ -439,7 +441,7 @@ impl<'a> ErasureState<'a> { pub fn erase_entry(&mut self, entry: &Entry) -> Box { let place = if let Some(res) = self.names.get(&entry.name.to_string()) { - res.clone() + *res } else { self.new_hole(entry.name.range, entry.name.to_string()) }; diff --git a/src/kind-pass/src/errors.rs b/src/kind-pass/src/errors.rs index 667852cb..ca5cb1d6 100644 --- a/src/kind-pass/src/errors.rs +++ b/src/kind-pass/src/errors.rs @@ -364,7 +364,7 @@ impl From for DiagnosticFrame { positions.push(Marker { position: error_range, color: Color::Fst, - text: format!("This expression is not the parameter"), + text: "This expression is not the parameter".to_string(), no_code: false, main: true, }) @@ -375,7 +375,7 @@ impl From for DiagnosticFrame { Marker { position: declaration_range, color: Color::Snd, - text: format!("This is the parameter that should be used"), + text: "This is the parameter that should be used".to_string(), no_code: false, main: false, } @@ -400,14 +400,14 @@ impl From for DiagnosticFrame { Marker { position: error_range, color: Color::Fst, - text: format!("This is not the type that is being declared"), + text: "This is not the type that is being declared".to_string(), no_code: false, main: true, }, Marker { position: declaration_range, color: Color::Snd, - text: format!("This is the type that should be used instead"), + text: "This is the type that should be used instead".to_string(), no_code: false, main: false, } diff --git a/src/kind-pass/src/expand/mod.rs b/src/kind-pass/src/expand/mod.rs index 8557f939..55c21e11 100644 --- a/src/kind-pass/src/expand/mod.rs +++ b/src/kind-pass/src/expand/mod.rs @@ -2,8 +2,8 @@ use fxhash::FxHashMap; use kind_derive::matching::derive_match; use kind_derive::open::derive_open; use kind_tree::concrete::{ - self, expr::Expr, Argument, Binding, Book, Entry, ExprKind, Literal, RecordDecl, SumTypeDecl, - Telescope, TopLevel, EntryMeta, + self, expr::Expr, Argument, Binding, Book, Entry, EntryMeta, ExprKind, Literal, RecordDecl, + SumTypeDecl, Telescope, TopLevel, }; /// Expands sum type and record definitions to a lot of /// helper definitions like eliminators and replace qualified identifiers @@ -24,7 +24,10 @@ pub fn expand_record_type(book: &mut FxHashMap, rec_ attrs: rec_type.attrs.clone(), }; - book.insert(rec_type.name.to_string(), (type_constructor, rec_type.extract_book_info())); + book.insert( + rec_type.name.to_string(), + (type_constructor, rec_type.extract_book_info()), + ); let irrelevant_params = rec_type.parameters.map(|x| x.to_implicit()); @@ -63,7 +66,13 @@ pub fn expand_record_type(book: &mut FxHashMap, rec_ docs: vec![], }; - book.insert(cons_ident.to_string(), (data_constructor, rec_type.extract_book_info_of_constructor())); + book.insert( + cons_ident.to_string(), + ( + data_constructor, + rec_type.extract_book_info_of_constructor(), + ), + ); } pub fn expand_sum_type(book: &mut FxHashMap, sum_type: &SumTypeDecl) { @@ -122,7 +131,7 @@ pub fn expand_sum_type(book: &mut FxHashMap, sum_typ range: cons_ident.range, }; - let book_info = cons.extract_book_info(&sum_type); + let book_info = cons.extract_book_info(sum_type); book.insert(cons_ident.to_string(), (data_constructor, book_info)); } } diff --git a/src/kind-pass/src/expand/uses.rs b/src/kind-pass/src/expand/uses.rs index d80694a2..ec01ec7f 100644 --- a/src/kind-pass/src/expand/uses.rs +++ b/src/kind-pass/src/expand/uses.rs @@ -1,18 +1,17 @@ -/// Expands sum type and record definitions to a lot of -/// helper definitions like eliminators and replace qualified identifiers -/// by their module names. - -use std::sync::mpsc::Sender; use fxhash::FxHashMap; use kind_report::data::DiagnosticFrame; use kind_tree::concrete::{visitor::Visitor, Module}; +/// Expands sum type and record definitions to a lot of +/// helper definitions like eliminators and replace qualified identifiers +/// by their module names. +use std::sync::mpsc::Sender; use crate::errors::PassError; pub struct Expand { pub names: FxHashMap, pub errors: Sender, - pub failed: bool + pub failed: bool, } impl Visitor for Expand { @@ -23,7 +22,9 @@ impl Visitor for Expand { let alias = match self.names.get(&ident.root.to_string()) { Some(path) => path, None => { - self.errors.send(PassError::CannotFindAlias(ident.root.to_string(), ident.range).into()).unwrap(); + self.errors + .send(PassError::CannotFindAlias(ident.root.to_string(), ident.range).into()) + .unwrap(); self.failed = true; return; } @@ -42,7 +43,7 @@ pub fn expand_uses(module: &mut Module, errors: Sender) -> bool let mut session = Expand { names: module.uses.clone(), errors, - failed: false + failed: false, }; for entry in module.entries.iter_mut() { session.visit_top_level(entry) diff --git a/src/kind-pass/src/unbound/mod.rs b/src/kind-pass/src/unbound/mod.rs index d62efce3..d77a28a3 100644 --- a/src/kind-pass/src/unbound/mod.rs +++ b/src/kind-pass/src/unbound/mod.rs @@ -79,7 +79,7 @@ impl Visitor for UnboundCollector { let entry = self .unbound .entry(ident.to_string()) - .or_insert_with(|| Vec::new()); + .or_insert_with(Vec::new); entry.push(ident.clone()); } } @@ -89,7 +89,7 @@ impl Visitor for UnboundCollector { let entry = self .unbound_top_level .entry(ident.to_string()) - .or_insert_with(|| Vec::new()); + .or_insert_with(Vec::new); entry.push(ident.clone()); } } @@ -374,14 +374,14 @@ impl Visitor for UnboundCollector { } ExprKind::Sigma(None, typ, body) => { self.visit_qualified_ident( - &mut QualifiedIdent::new_static("Sigma", None, expr.range).to_sugar(), + QualifiedIdent::new_static("Sigma", None, expr.range).to_sugar(), ); self.visit_expr(typ); self.visit_expr(body); } ExprKind::Sigma(Some(ident), typ, body) => { self.visit_qualified_ident( - &mut QualifiedIdent::new_static("Sigma", None, expr.range).to_sugar(), + QualifiedIdent::new_static("Sigma", None, expr.range).to_sugar(), ); self.visit_expr(typ); self.context_vars.push((ident.range, ident.to_string())); @@ -389,7 +389,7 @@ impl Visitor for UnboundCollector { self.context_vars.pop(); } ExprKind::Match(matcher) => { - self.visit_qualified_ident(&mut matcher.typ.add_segment("match").to_sugar()); + self.visit_qualified_ident(matcher.typ.add_segment("match").to_sugar()); self.visit_ident(&mut Ident::new_by_sugar( &format!("{}.match", matcher.typ.to_string().as_str()), expr.range, @@ -411,8 +411,8 @@ impl Visitor for UnboundCollector { } ExprKind::Hole => {} ExprKind::Do(typ, sttm) => { - self.visit_qualified_ident(&mut typ.add_segment("pure").to_sugar()); - self.visit_qualified_ident(&mut typ.add_segment("bind").to_sugar()); + self.visit_qualified_ident(typ.add_segment("pure").to_sugar()); + self.visit_qualified_ident(typ.add_segment("bind").to_sugar()); self.visit_sttm(sttm) } ExprKind::If(cond, if_, else_) => { diff --git a/src/kind-report/src/lib.rs b/src/kind-report/src/lib.rs index 6271f9e1..73ed7da5 100644 --- a/src/kind-report/src/lib.rs +++ b/src/kind-report/src/lib.rs @@ -77,4 +77,4 @@ pub fn check_if_utf8_is_supported<'a>(disable: bool, indent: usize) -> RenderCon } else { RenderConfig::unicode(indent) } -} \ No newline at end of file +} diff --git a/src/kind-report/src/report.rs b/src/kind-report/src/report.rs index 6aa8f434..bc6f008f 100644 --- a/src/kind-report/src/report.rs +++ b/src/kind-report/src/report.rs @@ -277,7 +277,10 @@ fn write_code_block<'a, T: Write + Sized>( } let code_lines: Vec<&'a str> = group_code.lines().collect(); - let mut lines = lines_set.iter().filter(|x| **x < code_lines.len()).collect::>(); + let mut lines = lines_set + .iter() + .filter(|x| **x < code_lines.len()) + .collect::>(); lines.sort(); for i in 0..lines.len() { @@ -409,7 +412,13 @@ impl<'a> Report for Diagnostic<'a> { match subtitle { Subtitle::Normal(color, phr) => { let colorizer = get_colorizer(color); - writeln!(fmt, "{:>5} {} {}", "", colorizer(config.chars.bullet), Paint::new(phr))?; + writeln!( + fmt, + "{:>5} {} {}", + "", + colorizer(config.chars.bullet), + Paint::new(phr) + )?; } Subtitle::Bold(color, phr) => { let colorizer = get_colorizer(color); @@ -444,7 +453,7 @@ impl<'a> Report for Diagnostic<'a> { } let groups = group_markers(&self.frame.positions); - let is_empty = groups.len() == 0; + let is_empty = groups.is_empty(); for (ctx, group) in groups { writeln!(fmt)?; diff --git a/src/kind-target-hvm/src/lib.rs b/src/kind-target-hvm/src/lib.rs index ac53ae8a..6c0e0fa8 100644 --- a/src/kind-target-hvm/src/lib.rs +++ b/src/kind-target-hvm/src/lib.rs @@ -11,7 +11,7 @@ pub fn compile_term(expr: &desugared::Expr) -> Box { }), Lambda(binder, body) => Box::new(Term::Lam { name: binder.to_string(), - body: compile_term(&body), + body: compile_term(body), }), App(head, spine) => spine.iter().fold(compile_term(head), |func, arg| { Box::new(Term::App { @@ -36,9 +36,9 @@ pub fn compile_term(expr: &desugared::Expr) -> Box { args: vec![compile_term(l), compile_term(r)], }), Hole(_) => unreachable!("Internal Error: 'Hole' cannot be a relevant term"), - | Typ => unreachable!("Internal Error: 'Typ' cannot be a relevant term"), - | U60 => unreachable!("Internal Error: 'U60' cannot be a relevant term"), - | All(_, _, _) => unreachable!("Internal Error: 'All' cannot be a relevant term"), + Typ => unreachable!("Internal Error: 'Typ' cannot be a relevant term"), + U60 => unreachable!("Internal Error: 'U60' cannot be a relevant term"), + All(_, _, _) => unreachable!("Internal Error: 'All' cannot be a relevant term"), Str(_) => unreachable!("Internal Error: 'Str' cannot be a relevant term"), Hlp(_) => unreachable!("Internal Error: 'Hlp' cannot be a relevant term"), Err => unreachable!("Internal Error: 'Err' cannot be a relevant term"), @@ -55,7 +55,7 @@ pub fn compile_rule(rule: desugared::Rule) -> Rule { } } -pub fn compile_entry(file: &mut File, entry: Box) { +pub fn compile_entry(file: &mut File, entry: desugared::Entry) { for rule in entry.rules { file.rules.push(compile_rule(rule)) } @@ -66,7 +66,7 @@ pub fn compile_book(book: desugared::Book) -> File { rules: Default::default(), }; for (_, entry) in book.entrs { - compile_entry(&mut file, entry); + compile_entry(&mut file, *entry); } file } diff --git a/src/kind-tree/src/concrete/mod.rs b/src/kind-tree/src/concrete/mod.rs index 7fb08778..f1a2b0e8 100644 --- a/src/kind-tree/src/concrete/mod.rs +++ b/src/kind-tree/src/concrete/mod.rs @@ -173,7 +173,7 @@ impl TopLevel { #[derive(Clone, Debug, PartialEq, Eq)] pub struct Module { pub entries: Vec, - pub uses: FxHashMap + pub uses: FxHashMap, } /// Metadata about entries, it's really useful when we @@ -292,7 +292,7 @@ impl Display for Module { impl Display for Book { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { - for (_, entr) in &self.entries { + for entr in self.entries.values() { write!(f, "{}", entr)?; } Ok(()) @@ -330,10 +330,10 @@ impl Display for Entry { write!(f, " {}", arg)?; } - write!(f, " : {}\n", &self.typ)?; + writeln!(f, " : {}", &self.typ)?; for rule in &self.rules { - write!(f, "{}\n", rule)? + writeln!(f, "{}", rule)? } Ok(()) @@ -592,7 +592,7 @@ impl Entry { hiddens, erased, arguments, - is_ctr: self.rules.len() == 0, + is_ctr: self.rules.is_empty(), range: self.name.range, } } diff --git a/src/kind-tree/src/concrete/visitor.rs b/src/kind-tree/src/concrete/visitor.rs index 171eafa6..b35e995c 100644 --- a/src/kind-tree/src/concrete/visitor.rs +++ b/src/kind-tree/src/concrete/visitor.rs @@ -370,7 +370,7 @@ pub fn walk_expr(ctx: &mut T, expr: &mut Expr) { for arg in spine { ctx.visit_binding(arg); } - }, + } ExprKind::All(None, typ, body) => { ctx.visit_expr(typ); ctx.visit_expr(body); diff --git a/src/kind-tree/src/symbol.rs b/src/kind-tree/src/symbol.rs index 269721da..1e6fa8ef 100644 --- a/src/kind-tree/src/symbol.rs +++ b/src/kind-tree/src/symbol.rs @@ -76,7 +76,7 @@ impl QualifiedIdent { QualifiedIdent { root: Symbol(format!("{}.{}", self.root.0, extension)), aux: self.aux.clone(), - range: self.range.clone(), + range: self.range, used_by_sugar: self.used_by_sugar, } } From bde129fbba30290ec0613677c7add406bc351080 Mon Sep 17 00:00:00 2001 From: Felipe g Date: Thu, 10 Nov 2022 09:49:32 -0300 Subject: [PATCH 8/9] feat: added command and fixes --- src/kind-cli/src/main.rs | 12 +++++++++++ src/kind-derive/src/matching.rs | 6 ++++-- src/kind-driver/src/lib.rs | 8 +++++-- src/kind-driver/src/resolution.rs | 30 +++----------------------- src/kind-pass/src/desugar/destruct.rs | 2 +- src/kind-pass/src/desugar/top_level.rs | 7 +++--- src/kind-pass/src/errors.rs | 15 +++++++++++++ src/kind-pass/src/unbound/mod.rs | 11 ++++------ 8 files changed, 48 insertions(+), 43 deletions(-) diff --git a/src/kind-cli/src/main.rs b/src/kind-cli/src/main.rs index fdd1039a..a4cc8018 100644 --- a/src/kind-cli/src/main.rs +++ b/src/kind-cli/src/main.rs @@ -50,6 +50,9 @@ enum Command { #[clap(aliases = &["e"])] Eval { file: String }, + #[clap(aliases = &["k"])] + ToKindCore { file : String }, + /// Runs Main on the HVM #[clap(aliases = &["r"])] Run { file: String }, @@ -199,6 +202,15 @@ fn main() { res }); } + Command::ToKindCore { file } => { + compile_in_session(render_config, root, file.clone(), &mut |session| { + driver::desugar_book(session, &PathBuf::from(file.clone())) + }) + .map(|res| { + print!("{}", res); + res + }); + } Command::GenChecker { file } => { compile_in_session(render_config, root, file.clone(), &mut |session| { driver::check_erasure_book(session, &PathBuf::from(file.clone())) diff --git a/src/kind-derive/src/matching.rs b/src/kind-derive/src/matching.rs index b66da19e..6b2a1b0f 100644 --- a/src/kind-derive/src/matching.rs +++ b/src/kind-derive/src/matching.rs @@ -225,7 +225,7 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { } // Rules - Entry { + let entry = Entry { name, docs: Vec::new(), args: types, @@ -233,5 +233,7 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { rules, range, attrs: Vec::new(), - } + }; + + entry } diff --git a/src/kind-driver/src/lib.rs b/src/kind-driver/src/lib.rs index a9528c24..6bc7f18f 100644 --- a/src/kind-driver/src/lib.rs +++ b/src/kind-driver/src/lib.rs @@ -49,6 +49,7 @@ pub fn to_book(session: &mut Session, path: &PathBuf) -> Option pub fn erase_book(session: &mut Session, path: &PathBuf) -> Option { let concrete_book = to_book(session, path)?; let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?; + println!("Desugared: {}", desugared_book); erasure::erase_book( &desugared_book, session.diagnostic_sender.clone(), @@ -56,6 +57,11 @@ pub fn erase_book(session: &mut Session, path: &PathBuf) -> Option Option { + let concrete_book = to_book(session, path)?; + desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book) +} + pub fn check_erasure_book(session: &mut Session, path: &PathBuf) -> Option { let concrete_book = to_book(session, path)?; let desugared_book = desugar::desugar_book(session.diagnostic_sender.clone(), &concrete_book)?; @@ -81,11 +87,9 @@ pub fn execute_file(file: &backend::File) -> Box { } pub fn eval_in_checker(book: &desugared::Book) -> Box { - // TODO: Change to from_file when hvm support it checker::eval_api(book) } pub fn generate_checker(book: &desugared::Book) -> String { - // TODO: Change to from_file when hvm support it checker::gen_checker(book) } diff --git a/src/kind-driver/src/resolution.rs b/src/kind-driver/src/resolution.rs index e98e2e55..74227f5e 100644 --- a/src/kind-driver/src/resolution.rs +++ b/src/kind-driver/src/resolution.rs @@ -3,7 +3,6 @@ //! it returns a desugared book of all of the //! depedencies. -use fxhash::FxHashMap; use kind_pass::expand::uses::expand_uses; use std::collections::HashSet; use std::fs; @@ -142,14 +141,13 @@ fn parse_and_store_book_by_identifier<'a>( session: &mut Session, ident: &QualifiedIdent, book: &'a mut Book, - unbound: &mut FxHashMap>, ) -> bool { if book.entries.contains_key(ident.to_string().as_str()) { return false; } match ident_to_path(&session.root, ident, true) { - Ok(Some(path)) => parse_and_store_book_by_path(session, &path, book, unbound), + Ok(Some(path)) => parse_and_store_book_by_path(session, &path, book), Ok(None) => true, Err(err) => { session.diagnostic_sender.send(err).unwrap(); @@ -162,7 +160,6 @@ fn parse_and_store_book_by_path<'a>( session: &mut Session, path: &PathBuf, book: &'a mut Book, - unbound: &mut FxHashMap>, ) -> bool { if session.loaded_paths_map.contains_key(path) { return false; @@ -195,16 +192,7 @@ fn parse_and_store_book_by_path<'a>( for idents in unbound_top_level.values() { if idents.iter().any(|x| !x.used_by_sugar) { - let res = parse_and_store_book_by_identifier(session, &idents[0], book, unbound); - failed |= res; - if res { - for ident in idents { - if !ident.used_by_sugar { - let entry = unbound.entry(ident.to_string()).or_default(); - entry.push(ident.clone()) - } - } - } + failed |= parse_and_store_book_by_identifier(session, &idents[0], book); } } @@ -230,20 +218,8 @@ fn unbound_variable(session: &mut Session, book: &Book, idents: &[Ident]) { pub fn parse_and_store_book(session: &mut Session, path: &PathBuf) -> Option { let mut book = Book::default(); - let mut unbound = FxHashMap::default(); - let failed = parse_and_store_book_by_path(session, path, &mut book, &mut unbound); - - for (_, res) in unbound { - unbound_variable( - session, - &book, - res.iter() - .map(|x| x.to_ident()) - .collect::>() - .as_slice(), - ) - } + let failed = parse_and_store_book_by_path(session, path, &mut book); if failed { None diff --git a/src/kind-pass/src/desugar/destruct.rs b/src/kind-pass/src/desugar/destruct.rs index 7fb6d2fe..6b4a491d 100644 --- a/src/kind-pass/src/desugar/destruct.rs +++ b/src/kind-pass/src/desugar/destruct.rs @@ -52,7 +52,7 @@ impl<'a> DesugarState<'a> { .collect(); if !jump_rest && !names.is_empty() { - self.send_err(PassError::NoCoverage(*type_info.0, names)) + self.send_err(PassError::NoFieldCoverage(*type_info.0, names)) } ordered_fields diff --git a/src/kind-pass/src/desugar/top_level.rs b/src/kind-pass/src/desugar/top_level.rs index b863e5d7..e7f58750 100644 --- a/src/kind-pass/src/desugar/top_level.rs +++ b/src/kind-pass/src/desugar/top_level.rs @@ -259,12 +259,11 @@ impl<'a> DesugarState<'a> { .old_book .count .get(head.to_string().as_str()) - .expect("Cannot find definition"); + .expect("Internal Error: Cannot find definition"); if !entry.is_ctr { - // TODO: Not sure if i should just throw an error? - // We are not requiring that the thing is specifically a constructor - //panic!("Incomplete Design: Oh no! {}", head) + // TODO: Check if only data constructors declared inside + // inductive types can be used in patterns. } let (hidden, _erased) = entry.arguments.count_implicits(); diff --git a/src/kind-pass/src/errors.rs b/src/kind-pass/src/errors.rs index ca5cb1d6..bd16a9a1 100644 --- a/src/kind-pass/src/errors.rs +++ b/src/kind-pass/src/errors.rs @@ -29,6 +29,7 @@ pub enum PassError { CannotFindAlias(String, Range), NotATypeConstructor(Range, Range), ShouldBeAParameter(Span, Range), + NoFieldCoverage(Range, Vec) } // TODO: A way to build an error message with methods @@ -413,6 +414,20 @@ impl From for DiagnosticFrame { } ], }, + PassError::NoFieldCoverage(place, other) => DiagnosticFrame { + code: 209, + severity: Severity::Error, + title: "The case is not covering all the values inside of it!".to_string(), + subtitles: vec![], + hints: vec![format!("Need variables for {}", other.iter().map(|x| format!("'{}'", x)).collect::>().join(", "))], + positions: vec![Marker { + position: place, + color: Color::Fst, + text: "This is the incomplete case".to_string(), + no_code: false, + main: true, + }], + }, } } } diff --git a/src/kind-pass/src/unbound/mod.rs b/src/kind-pass/src/unbound/mod.rs index d77a28a3..5cc89695 100644 --- a/src/kind-pass/src/unbound/mod.rs +++ b/src/kind-pass/src/unbound/mod.rs @@ -114,11 +114,12 @@ impl Visitor for UnboundCollector { None => (), } - if let Some(fst) = self + let res = self .context_vars .iter() - .find(|x| x.1 == argument.name.to_string()) - { + .find(|x| x.1 == argument.name.to_string()); + + if let Some(fst) = res { self.errors .send(PassError::RepeatedVariable(fst.0, argument.name.range).into()) .unwrap() @@ -390,10 +391,6 @@ impl Visitor for UnboundCollector { } ExprKind::Match(matcher) => { self.visit_qualified_ident(matcher.typ.add_segment("match").to_sugar()); - self.visit_ident(&mut Ident::new_by_sugar( - &format!("{}.match", matcher.typ.to_string().as_str()), - expr.range, - )); self.visit_match(matcher) } ExprKind::Subst(subst) => { From 135b1fda86799aa4a50c7130428b040c741fbb18 Mon Sep 17 00:00:00 2001 From: Felipe g Date: Thu, 10 Nov 2022 11:43:14 -0300 Subject: [PATCH 9/9] fix: fixed things in name resolution --- src/kind-derive/src/matching.rs | 2 +- src/kind-driver/src/errors.rs | 2 +- src/kind-driver/src/resolution.rs | 34 +++++++++++++++++-------------- src/kind-pass/src/desugar/expr.rs | 2 +- src/kind-pass/src/errors.rs | 24 +++++++++++++++++++++- src/kind-pass/src/unbound/mod.rs | 21 +++++++++++++++++-- 6 files changed, 64 insertions(+), 21 deletions(-) diff --git a/src/kind-derive/src/matching.rs b/src/kind-derive/src/matching.rs index 6b2a1b0f..d7ac75bf 100644 --- a/src/kind-derive/src/matching.rs +++ b/src/kind-derive/src/matching.rs @@ -151,7 +151,7 @@ pub fn derive_match(range: Range, sum: &SumTypeDecl) -> concrete::Entry { types.push(Argument { hidden: false, erased: false, - name: Ident::new_static("_", range), + name: Ident::new_static(&format!("_{}", cons.name.to_string()), range), typ: Some(cons_type), range, }); diff --git a/src/kind-driver/src/errors.rs b/src/kind-driver/src/errors.rs index 666b6eba..81b35afb 100644 --- a/src/kind-driver/src/errors.rs +++ b/src/kind-driver/src/errors.rs @@ -61,7 +61,7 @@ impl From for DiagnosticFrame { DriverError::DefinedMultipleTimes(fst, snd) => DiagnosticFrame { code: 102, severity: Severity::Error, - title: "Multiple paths for the same name".to_string(), + title: "Defined multiple times for the same name".to_string(), subtitles: vec![], hints: vec![ "Rename one of the definitions or remove and look at how names work in Kind at https://kind.kindelia.org/hints/names".to_string() diff --git a/src/kind-driver/src/resolution.rs b/src/kind-driver/src/resolution.rs index 74227f5e..addb11d1 100644 --- a/src/kind-driver/src/resolution.rs +++ b/src/kind-driver/src/resolution.rs @@ -72,18 +72,22 @@ fn ident_to_path( } } -fn try_to_insert_new_name<'a>(session: &'a Session, ident: QualifiedIdent, book: &'a mut Book) { +fn try_to_insert_new_name<'a>(failed: &mut bool, session: &'a Session, ident: QualifiedIdent, book: &'a mut Book) -> bool { if let Some(first_occorence) = book.names.get(ident.to_string().as_str()) { session .diagnostic_sender .send(DriverError::DefinedMultipleTimes(first_occorence.clone(), ident).into()) .unwrap(); + *failed = true; + false } else { book.names.insert(ident.to_string(), ident); + true } } fn module_to_book<'a>( + failed: &mut bool, session: &'a Session, module: &Module, book: &'a mut Book, @@ -94,25 +98,25 @@ fn module_to_book<'a>( match &entry { TopLevel::SumType(sum) => { public_names.insert(sum.name.to_string()); - try_to_insert_new_name(session, sum.name.clone(), book); - book.count - .insert(sum.name.to_string(), sum.extract_book_info()); - - book.entries.insert(sum.name.to_string(), entry.clone()); + if try_to_insert_new_name(failed, session, sum.name.clone(), book) { + book.count.insert(sum.name.to_string(), sum.extract_book_info()); + book.entries.insert(sum.name.to_string(), entry.clone()); + } for cons in &sum.constructors { - let cons_ident = sum.name.add_segment(cons.name.to_str()); - public_names.insert(cons_ident.to_string()); - book.count - .insert(cons_ident.to_string(), cons.extract_book_info(sum)); - try_to_insert_new_name(session, cons_ident, book); + let mut cons_ident = sum.name.add_segment(cons.name.to_str()); + cons_ident.range = cons.name.range.clone(); + if try_to_insert_new_name(failed, session, cons_ident.clone(), book) { + public_names.insert(cons_ident.to_string()); + book.count.insert(cons_ident.to_string(), cons.extract_book_info(sum)); + } } } TopLevel::RecordType(rec) => { public_names.insert(rec.name.to_string()); book.count .insert(rec.name.to_string(), rec.extract_book_info()); - try_to_insert_new_name(session, rec.name.clone(), book); + try_to_insert_new_name(failed, session, rec.name.clone(), book); book.entries.insert(rec.name.to_string(), entry.clone()); @@ -122,10 +126,10 @@ fn module_to_book<'a>( cons_ident.to_string(), rec.extract_book_info_of_constructor(), ); - try_to_insert_new_name(session, cons_ident, book); + try_to_insert_new_name(failed, session, cons_ident, book); } TopLevel::Entry(entr) => { - try_to_insert_new_name(session, entr.name.clone(), book); + try_to_insert_new_name(failed, session, entr.name.clone(), book); public_names.insert(entr.name.to_string()); book.count .insert(entr.name.to_string(), entr.extract_book_info()); @@ -198,7 +202,7 @@ fn parse_and_store_book_by_path<'a>( failed |= expand_uses(&mut module, session.diagnostic_sender.clone()); - module_to_book(session, &module, book); + module_to_book(&mut failed, session, &module, book); failed } diff --git a/src/kind-pass/src/desugar/expr.rs b/src/kind-pass/src/desugar/expr.rs index 6143db43..3a1c6017 100644 --- a/src/kind-pass/src/desugar/expr.rs +++ b/src/kind-pass/src/desugar/expr.rs @@ -144,7 +144,7 @@ impl<'a> DesugarState<'a> { let name = match name { Some(ident) => ident.clone(), - None => Ident::generate("_"), + None => Ident::generate("_var"), }; let spine = vec![ diff --git a/src/kind-pass/src/errors.rs b/src/kind-pass/src/errors.rs index bd16a9a1..4f5f0ad0 100644 --- a/src/kind-pass/src/errors.rs +++ b/src/kind-pass/src/errors.rs @@ -29,7 +29,8 @@ pub enum PassError { CannotFindAlias(String, Range), NotATypeConstructor(Range, Range), ShouldBeAParameter(Span, Range), - NoFieldCoverage(Range, Vec) + NoFieldCoverage(Range, Vec), + DuplicatedConstructor(Range, Range), } // TODO: A way to build an error message with methods @@ -428,6 +429,27 @@ impl From for DiagnosticFrame { main: true, }], }, + PassError::DuplicatedConstructor(place, other) => DiagnosticFrame { + code: 209, + severity: Severity::Error, + title: "Duplicated constructor name".to_string(), + subtitles: vec![], + hints: vec![], + positions: vec![Marker { + position: place, + color: Color::Fst, + text: "Here".to_string(), + no_code: false, + main: true, + }, + Marker { + position: other, + color: Color::Fst, + text: "Here".to_string(), + no_code: false, + main: false, + }], + }, } } } diff --git a/src/kind-pass/src/unbound/mod.rs b/src/kind-pass/src/unbound/mod.rs index 5cc89695..a20677c7 100644 --- a/src/kind-pass/src/unbound/mod.rs +++ b/src/kind-pass/src/unbound/mod.rs @@ -165,10 +165,27 @@ impl Visitor for UnboundCollector { TopLevel::SumType(entr) => { self.context_vars .push((entr.name.range, entr.name.to_string())); + + let mut repeated_names = FxHashMap::::default(); + let mut failed = false; + for cons in &entr.constructors { + + match repeated_names.get(&cons.name.to_string()) { + Some(_) => { + failed = true; + }, + None => { + repeated_names.insert(cons.name.to_string(), cons.name.range); + }, + } + let name_cons = entr.name.add_segment(cons.name.to_str()); - self.context_vars - .push((name_cons.range, name_cons.to_string())); + self.context_vars.push((name_cons.range, name_cons.to_string())); + } + + if failed { + return; } let vars = self.context_vars.clone();