From e55dbbfb65a6e779c2b9528b65a078611b6f3cec Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Thu, 1 Aug 2024 13:29:36 -0300 Subject: [PATCH 01/24] Experiment with ranged diagnostics --- src/diagnostics.rs | 57 ++++++++++++++++++++++++++++++++++-------- src/fun/net_to_term.rs | 2 +- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 2b436e9c3..bd4dbaa03 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -26,14 +26,30 @@ pub struct DiagnosticsConfig { pub import_shadow: Severity, } +#[derive(Debug, Copy, Clone, Hash)] +pub struct TextRange { + pub line: usize, + pub char: usize, +} + +#[derive(Debug, Clone, Hash)] +pub struct FileRange { + pub range: TextRange, + // Storing files as Strings, could be done as file IDs in the future + pub file: String, +} + #[derive(Debug, Clone)] pub struct Diagnostic { - message: String, - severity: Severity, + pub message: String, + pub severity: Severity, + pub range: Option, } #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum DiagnosticOrigin { + /// An error when parsing source code. + Parsing, /// An error from the relationship between multiple top-level definitions. Book, /// An error in a pattern-matching function definition rule. @@ -68,19 +84,29 @@ impl Diagnostics { Self { err_counter: 0, diagnostics: Default::default(), config } } + pub fn add_parsing_error(&mut self, err: impl std::fmt::Display, range: Option) { + self.err_counter += 1; + self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Parsing, range); + } + pub fn add_book_error(&mut self, err: impl std::fmt::Display) { self.err_counter += 1; - self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Book); + self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Book, None); } pub fn add_rule_error(&mut self, err: impl std::fmt::Display, def_name: Name) { self.err_counter += 1; - self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Rule(def_name.def_name_from_generated())); + self.add_diagnostic( + err, + Severity::Error, + DiagnosticOrigin::Rule(def_name.def_name_from_generated()), + None, + ); } pub fn add_inet_error(&mut self, err: impl std::fmt::Display, def_name: String) { self.err_counter += 1; - self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Inet(def_name)); + self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Inet(def_name), None); } pub fn add_rule_warning(&mut self, warn: impl std::fmt::Display, warn_type: WarningType, def_name: Name) { @@ -88,7 +114,7 @@ impl Diagnostics { if severity == Severity::Error { self.err_counter += 1; } - self.add_diagnostic(warn, severity, DiagnosticOrigin::Rule(def_name.def_name_from_generated())); + self.add_diagnostic(warn, severity, DiagnosticOrigin::Rule(def_name.def_name_from_generated()), None); } pub fn add_book_warning(&mut self, warn: impl std::fmt::Display, warn_type: WarningType) { @@ -96,11 +122,17 @@ impl Diagnostics { if severity == Severity::Error { self.err_counter += 1; } - self.add_diagnostic(warn, severity, DiagnosticOrigin::Book); + self.add_diagnostic(warn, severity, DiagnosticOrigin::Book, None); } - pub fn add_diagnostic(&mut self, msg: impl ToString, severity: Severity, orig: DiagnosticOrigin) { - let diag = Diagnostic { message: msg.to_string(), severity }; + pub fn add_diagnostic( + &mut self, + msg: impl ToString, + severity: Severity, + orig: DiagnosticOrigin, + range: Option, + ) { + let diag = Diagnostic { message: msg.to_string(), severity, range }; self.diagnostics.entry(orig).or_default().push(diag) } @@ -171,6 +203,11 @@ impl Diagnostics { let mut errs = filter(errs, severity).peekable(); if errs.peek().is_some() { match orig { + DiagnosticOrigin::Parsing => { + for err in errs { + writeln!(f, "{err}")?; + } + } DiagnosticOrigin::Book => { for err in errs { writeln!(f, "{err}")?; @@ -223,7 +260,7 @@ impl From for Diagnostics { Self { diagnostics: BTreeMap::from_iter([( DiagnosticOrigin::Book, - vec![Diagnostic { message: value, severity: Severity::Error }], + vec![Diagnostic { message: value, severity: Severity::Error, range: None }], )]), ..Default::default() } diff --git a/src/fun/net_to_term.rs b/src/fun/net_to_term.rs index 290e689ea..27a2d252a 100644 --- a/src/fun/net_to_term.rs +++ b/src/fun/net_to_term.rs @@ -550,7 +550,7 @@ impl Reader<'_> { for (err, count) in err_counts { let count_msg = if count > 1 { format!(" ({count} occurrences)") } else { "".to_string() }; let msg = format!("{}{}", err, count_msg); - diagnostics.add_diagnostic(msg.as_str(), Severity::Warning, DiagnosticOrigin::Readback); + diagnostics.add_diagnostic(msg.as_str(), Severity::Warning, DiagnosticOrigin::Readback, None); } } From 8426a3c0dd616fc71e7818449bd5e56f680fe88b Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Tue, 6 Aug 2024 12:31:30 -0300 Subject: [PATCH 02/24] Change `Parser` to error with span information --- Cargo.lock | 8 ++- Cargo.toml | 6 ++- src/diagnostics.rs | 14 ++++++ src/fun/parser.rs | 49 ++++++++++++++----- src/imp/parser.rs | 6 ++- ...rse_file__repeated_datatype_name.bend.snap | 6 ++- 6 files changed, 68 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a88c0e47..5f2dee61e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,8 +5,7 @@ version = 3 [[package]] name = "TSPL" version = "0.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52dfd6238b1461b99635b26585a85b4e7b9c786cc0481b3c540ae5f590b6dfb6" +source = "git+https://github.com/HigherOrderCO/TSPL.git?branch=range-info#ae25a5f5e3a805e4ae8854b34b6f29954ec2b68f" dependencies = [ "highlight_error", ] @@ -192,9 +191,8 @@ checksum = "809e18805660d7b6b2e2b9f316a5099521b5998d5cba4dda11b5157a21aaef03" [[package]] name = "hvm" -version = "2.0.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "281675413d2dd76cb1c53ec0d318bb672f5d70fb825929af6bcadd9b7f78c11b" +version = "2.0.21" +source = "git+https://github.com/higherorderco/hvm.git?branch=parser-update#01b795d8718cae14c7809316ac7b2acf459b0dba" dependencies = [ "TSPL", "cc", diff --git a/Cargo.toml b/Cargo.toml index ddcbb601f..4a595ed9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ cli = ["dep:clap"] TSPL = "0.0.12" clap = { version = "4.4.1", features = ["derive"], optional = true } highlight_error = "0.1.1" -hvm = "=2.0.19" +hvm = "2.0.21" indexmap = "2.2.3" interner = "0.2.1" itertools = "0.11.0" @@ -41,3 +41,7 @@ walkdir = "2.3.3" [profile.test] opt-level = 2 + +[patch.crates-io] +TSPL = { git = "https://github.com/HigherOrderCO/TSPL.git", branch = "range-info" } +hvm = { git = "https://github.com/higherorderco/hvm.git", branch = "parser-update" } diff --git a/src/diagnostics.rs b/src/diagnostics.rs index bd4dbaa03..5c963b7d9 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -1,3 +1,5 @@ +use TSPL::ParseError; + use crate::fun::{display::DisplayFn, Name}; use std::{ collections::BTreeMap, @@ -267,6 +269,18 @@ impl From for Diagnostics { } } +impl From for Diagnostics { + fn from(value: ParseError) -> Self { + Self { + diagnostics: BTreeMap::from_iter([( + DiagnosticOrigin::Parsing, + vec![Diagnostic { message: value.into(), severity: Severity::Error, range: None }], + )]), + ..Default::default() + } + } +} + impl DiagnosticsConfig { pub fn new(severity: Severity, verbose: bool) -> Self { Self { diff --git a/src/fun/parser.rs b/src/fun/parser.rs index 3046070f3..c04d81518 100644 --- a/src/fun/parser.rs +++ b/src/fun/parser.rs @@ -12,7 +12,7 @@ use crate::{ use highlight_error::highlight_error; use indexmap::IndexMap; use itertools::Itertools; -use TSPL::Parser; +use TSPL::{ParseError, Parser}; type FunDefinition = super::Definition; type ImpDefinition = crate::imp::Definition; @@ -97,7 +97,7 @@ impl ParseBook { // ::= ([0-9]+ | "0x"[0-9a-fA-F]+ | "0b"[01]+) // ::= ( "+" | "-" | "*" | "/" | "%" | "==" | "!=" | "<<" | ">>" | "<" | ">" | "&" | "|" | "^" | "**" ) -pub type ParseResult = std::result::Result; +pub type ParseResult = std::result::Result; pub struct TermParser<'i> { input: &'i str, @@ -252,7 +252,8 @@ impl<'a> TermParser<'a> { let fields = self.list_like(parse_field, "", ")", "", false, 0)?; if let Some(field) = fields.find_repeated_names().into_iter().next() { - return Err(format!("Found a repeated field '{field}' in constructor {ctr_name}.")); + let msg = format!("Found a repeated field '{field}' in constructor {ctr_name}."); + return self.expected_and("field", &msg)?; } Ok((ctr_name, fields)) } else { @@ -280,7 +281,7 @@ impl<'a> TermParser<'a> { Ok(def) } - fn parse_from_import(&mut self) -> Result { + fn parse_from_import(&mut self) -> ParseResult { // from path import package // from path import (a, b) // from path import * @@ -302,7 +303,7 @@ impl<'a> TermParser<'a> { Ok(Import::new(path, ImportType::Single(import, alias), relative)) } - fn parse_import(&mut self) -> Result, String> { + fn parse_import(&mut self) -> ParseResult> { // import path // import (path/a, path/b) @@ -844,7 +845,7 @@ impl<'a> TermParser<'a> { /// Parses a tag where it may or may not be valid. /// /// If it is not valid, the returned callback can be used to issue an error. - fn parse_tag(&mut self) -> ParseResult<(Option, impl FnOnce(&mut Self) -> Result<(), String>)> { + fn parse_tag(&mut self) -> ParseResult<(Option, impl FnOnce(&mut Self) -> Result<(), ParseError>)> { let index = self.index; self.skip_trivia(); let tag = if self.peek_one() == Some('#') @@ -1008,7 +1009,8 @@ impl<'a> TermParser<'a> { } else { for ctr in adt.ctrs.keys() { if let Some(builtin) = book.contains_builtin_def(ctr) { - return Err(TermParser::redefinition_of_function_msg(builtin, ctr)); + let msg = TermParser::redefinition_of_function_msg(builtin, ctr); + return self.expected_and("function", &msg); } match book.ctrs.entry(ctr.clone()) { indexmap::map::Entry::Vacant(e) => _ = e.insert(nam.clone()), @@ -1093,6 +1095,15 @@ impl<'a> Parser<'a> for TermParser<'a> { self.expected_spanned(exp, ini_idx..end_idx) } + /// Generates an error message with an additional custom message. + /// + /// Override to have our own error message. + fn expected_and(&mut self, exp: &str, msg: &str) -> ParseResult { + let ini_idx = *self.index(); + let end_idx = *self.index() + 1; + self.expected_spanned_and(exp, msg, ini_idx..end_idx) + } + /// Consumes an instance of the given string, erroring if it is not found. /// /// Override to have our own error message. @@ -1226,7 +1237,7 @@ pub trait ParserCommons<'a>: Parser<'a> { } } - fn parse_import_name(&mut self, label: &str) -> Result<(Name, Option, bool), String> { + fn parse_import_name(&mut self, label: &str) -> ParseResult<(Name, Option, bool)> { let (import, alias) = self.parse_name_maybe_alias(label)?; let relative = import.starts_with("./") | import.starts_with("../"); Ok((import, alias, relative)) @@ -1331,10 +1342,21 @@ pub trait ParserCommons<'a>: Parser<'a> { self.with_ctx(Err(msg), span) } + fn expected_spanned_and(&mut self, exp: &str, msg: &str, span: Range) -> ParseResult { + let is_eof = self.is_eof(); + let detected = DisplayFn(|f| if is_eof { write!(f, " end of input") } else { Ok(()) }); + let msg = format!( + "\x1b[1m- information:\x1b[0m {}\n\x1b[1m- expected:\x1b[0m {}\n\x1b[1m- detected:\x1b[0m{}", + msg, exp, detected, + ); + self.with_ctx(Err(msg), span) + } + fn with_ctx(&mut self, res: Result, span: Range) -> ParseResult { res.map_err(|msg| { let ctx = highlight_error(span.start, span.end, self.input()); - format!("{msg}\n{ctx}") + let msg = format!("{msg}\n{ctx}"); + ParseError::new((span.start, span.end), msg) }) } @@ -1533,7 +1555,8 @@ pub trait ParserCommons<'a>: Parser<'a> { if next_is_hex || num_str.is_empty() { self.expected(format!("valid {radix} digit").as_str()) } else { - u32::from_str_radix(&num_str, radix as u32).map_err(|e| e.to_string()) + u32::from_str_radix(&num_str, radix as u32) + .map_err(|e| self.expected_and::("integer", &e.to_string()).unwrap_err()) } } @@ -1544,7 +1567,8 @@ pub trait ParserCommons<'a>: Parser<'a> { if next_is_hex || num_str.is_empty() { self.expected(format!("valid {radix} digit").as_str()) } else { - u32::from_str_radix(&num_str, radix as u32).map_err(|e| e.to_string()) + u32::from_str_radix(&num_str, radix as u32) + .map_err(|e| self.expected_and::("integer", &e.to_string()).unwrap_err()) } } @@ -1573,7 +1597,8 @@ pub trait ParserCommons<'a>: Parser<'a> { self.advance_one(); let fra_str = self.take_while(|c| c.is_digit(radix as u32) || c == '_'); let fra_str = fra_str.chars().filter(|c| *c != '_').collect::(); - let fra = u32::from_str_radix(&fra_str, radix as u32).map_err(|e| e.to_string())?; + let fra = u32::from_str_radix(&fra_str, radix as u32) + .map_err(|e| self.expected_and::("integer", &e.to_string()).unwrap_err())?; let fra = fra as f32 / (radix.to_f32()).powi(fra_str.len() as i32); Some(fra) } else { diff --git a/src/imp/parser.rs b/src/imp/parser.rs index fe6b94bbc..a986062e0 100644 --- a/src/imp/parser.rs +++ b/src/imp/parser.rs @@ -1080,7 +1080,8 @@ impl<'a> PyParser<'a> { fields = self.list_like(|p| p.parse_variant_field(), "{", "}", ",", true, 0)?; } if let Some(field) = fields.find_repeated_names().into_iter().next() { - return Err(format!("Found a repeated field '{field}' in constructor {ctr_name}.")); + let msg = format!("Found a repeated field '{field}' in constructor {ctr_name}."); + return self.expected_and("field", &msg); } Ok(Variant { name: ctr_name, fields }) } @@ -1101,7 +1102,8 @@ impl<'a> PyParser<'a> { vec![] }; if let Some(field) = fields.find_repeated_names().into_iter().next() { - return Err(format!("Found a repeated field '{field}' in object {name}.")); + let msg = format!("Found a repeated field '{field}' in object {name}."); + return self.expected_and("field", &msg); } if !self.is_eof() { self.consume_new_line()?; diff --git a/tests/snapshots/parse_file__repeated_datatype_name.bend.snap b/tests/snapshots/parse_file__repeated_datatype_name.bend.snap index ea0a83853..59e8aacd4 100644 --- a/tests/snapshots/parse_file__repeated_datatype_name.bend.snap +++ b/tests/snapshots/parse_file__repeated_datatype_name.bend.snap @@ -4,4 +4,8 @@ input_file: tests/golden_tests/parse_file/repeated_datatype_name.bend --- Errors: In tests/golden_tests/parse_file/repeated_datatype_name.bend : -Found a repeated field 'Expr' in constructor Expr/Plus. +- information: Found a repeated field 'Expr' in constructor Expr/Plus. +- expected: field +- detected: + 3 | | (Plus Expr Expr) + From 7cd4ddfc97c70345e44c83691345b24cbe603ea1 Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Tue, 6 Aug 2024 16:38:01 -0300 Subject: [PATCH 03/24] Add file and span information to parsing error diagnostics --- src/diagnostics.rs | 22 ++++++++++++-------- src/fun/load_book.rs | 49 +++++++++++++++++++++++++++++++++++++++----- src/imp/to_fun.rs | 7 ++++--- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 5c963b7d9..e955d657b 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -29,14 +29,16 @@ pub struct DiagnosticsConfig { } #[derive(Debug, Copy, Clone, Hash)] -pub struct TextRange { +pub struct TextLocation { pub line: usize, pub char: usize, } +pub type TextSpan = (TextLocation, TextLocation); + #[derive(Debug, Clone, Hash)] -pub struct FileRange { - pub range: TextRange, +pub struct FileSpan { + pub span: TextSpan, // Storing files as Strings, could be done as file IDs in the future pub file: String, } @@ -45,7 +47,7 @@ pub struct FileRange { pub struct Diagnostic { pub message: String, pub severity: Severity, - pub range: Option, + pub range: Option, } #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] @@ -86,9 +88,9 @@ impl Diagnostics { Self { err_counter: 0, diagnostics: Default::default(), config } } - pub fn add_parsing_error(&mut self, err: impl std::fmt::Display, range: Option) { + pub fn add_parsing_error(&mut self, err: impl std::fmt::Display, span: FileSpan) { self.err_counter += 1; - self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Parsing, range); + self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Parsing, Some(span)); } pub fn add_book_error(&mut self, err: impl std::fmt::Display) { @@ -132,7 +134,7 @@ impl Diagnostics { msg: impl ToString, severity: Severity, orig: DiagnosticOrigin, - range: Option, + range: Option, ) { let diag = Diagnostic { message: msg.to_string(), severity, range }; self.diagnostics.entry(orig).or_default().push(diag) @@ -274,6 +276,7 @@ impl From for Diagnostics { Self { diagnostics: BTreeMap::from_iter([( DiagnosticOrigin::Parsing, + // TODO: range is not because we're missing the origin file, can we fix this? vec![Diagnostic { message: value.into(), severity: Severity::Error, range: None }], )]), ..Default::default() @@ -321,6 +324,9 @@ impl Default for DiagnosticsConfig { impl Display for Diagnostic { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.message) + match &self.range { + Some(FileSpan { file, .. }) => write!(f, "In {}: \n{}", file, self.message), + None => write!(f, "{}", self.message), + } } } diff --git a/src/fun/load_book.rs b/src/fun/load_book.rs index db1bd1211..84fb70582 100644 --- a/src/fun/load_book.rs +++ b/src/fun/load_book.rs @@ -1,9 +1,9 @@ use super::{ - parser::{ParseBook, TermParser}, + parser::{ParseBook, ParseResult, TermParser}, Book, Name, }; use crate::{ - diagnostics::{Diagnostics, DiagnosticsConfig}, + diagnostics::{Diagnostics, DiagnosticsConfig, FileSpan, TextLocation, TextSpan}, imports::PackageLoader, }; use std::path::Path; @@ -39,11 +39,50 @@ pub fn load_to_book( book.load_imports(package_loader, diag) } -pub fn do_parse_book(code: &str, origin: &Path, mut book: ParseBook) -> Result { +pub fn do_parse_book(code: &str, origin: &Path, mut book: ParseBook) -> Result { book.source = Name::new(origin.to_string_lossy()); - TermParser::new(code).parse_book(book, false).map_err(|e| format!("In {} :\n{}", origin.display(), e)) + TermParser::new(code).parse_book(book, false).map_err(|err| { + let mut diagnostics = Diagnostics::default(); + let span = byte_span_to_line(code, err.span); + diagnostics.add_parsing_error(err, FileSpan { span, file: origin.to_string_lossy().into() }); + diagnostics + }) } -pub fn do_parse_book_default(code: &str, origin: &Path) -> Result { +pub fn do_parse_book_default(code: &str, origin: &Path) -> Result { do_parse_book(code, origin, ParseBook::builtins())?.to_fun() } + +fn byte_span_to_line(code: &str, span: (usize, usize)) -> TextSpan { + // Will loop for way too long otherwise + assert!(span.0 <= span.1); + + let mut start_line = 0; + let mut start_char = 0; + let mut end_line = 0; + let mut end_char = 0; + + let mut curr_idx = 0; + while curr_idx <= span.0 { + if code.as_bytes()[curr_idx] == b'\n' { + start_line += 1; + end_line += 1; + start_char = 0; + } else { + start_char += 1; + } + curr_idx += 1; + } + + while curr_idx <= span.1 { + if code.as_bytes()[curr_idx] == b'\n' { + end_line += 1; + end_char = 0; + } else { + end_char += 1; + } + curr_idx += 1; + } + + (TextLocation { line: start_line, char: start_char }, TextLocation { line: end_line, char: end_char }) +} diff --git a/src/imp/to_fun.rs b/src/imp/to_fun.rs index 1c419c1ec..a4f118a87 100644 --- a/src/imp/to_fun.rs +++ b/src/imp/to_fun.rs @@ -1,13 +1,14 @@ use super::{AssignPattern, Definition, Expr, InPlaceOp, Stmt}; -use crate::fun::{ +use crate::{diagnostics::Diagnostics, fun::{ self, builtins::{LCONS, LNIL}, parser::ParseBook, Book, Name, -}; +}}; impl ParseBook { - pub fn to_fun(mut self) -> Result { + // TODO: Change all functions to return diagnostics + pub fn to_fun(mut self) -> Result { for (name, mut def) in std::mem::take(&mut self.imp_defs) { def.order_kwargs(&self)?; def.gen_map_get(); From 8ba7f95bf4a7dd8c904f68999fe6cac915b3a1db Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Tue, 6 Aug 2024 16:48:13 -0300 Subject: [PATCH 04/24] Change `range` to `span` --- src/diagnostics.rs | 10 +++++----- src/fun/load_book.rs | 2 +- src/imp/to_fun.rs | 15 +++++++++------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/diagnostics.rs b/src/diagnostics.rs index e955d657b..7cfbf9fb1 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -47,7 +47,7 @@ pub struct FileSpan { pub struct Diagnostic { pub message: String, pub severity: Severity, - pub range: Option, + pub span: Option, } #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] @@ -136,7 +136,7 @@ impl Diagnostics { orig: DiagnosticOrigin, range: Option, ) { - let diag = Diagnostic { message: msg.to_string(), severity, range }; + let diag = Diagnostic { message: msg.to_string(), severity, span: range }; self.diagnostics.entry(orig).or_default().push(diag) } @@ -264,7 +264,7 @@ impl From for Diagnostics { Self { diagnostics: BTreeMap::from_iter([( DiagnosticOrigin::Book, - vec![Diagnostic { message: value, severity: Severity::Error, range: None }], + vec![Diagnostic { message: value, severity: Severity::Error, span: None }], )]), ..Default::default() } @@ -277,7 +277,7 @@ impl From for Diagnostics { diagnostics: BTreeMap::from_iter([( DiagnosticOrigin::Parsing, // TODO: range is not because we're missing the origin file, can we fix this? - vec![Diagnostic { message: value.into(), severity: Severity::Error, range: None }], + vec![Diagnostic { message: value.into(), severity: Severity::Error, span: None }], )]), ..Default::default() } @@ -324,7 +324,7 @@ impl Default for DiagnosticsConfig { impl Display for Diagnostic { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - match &self.range { + match &self.span { Some(FileSpan { file, .. }) => write!(f, "In {}: \n{}", file, self.message), None => write!(f, "{}", self.message), } diff --git a/src/fun/load_book.rs b/src/fun/load_book.rs index 84fb70582..6ebdd4e8e 100644 --- a/src/fun/load_book.rs +++ b/src/fun/load_book.rs @@ -1,5 +1,5 @@ use super::{ - parser::{ParseBook, ParseResult, TermParser}, + parser::{ParseBook, TermParser}, Book, Name, }; use crate::{ diff --git a/src/imp/to_fun.rs b/src/imp/to_fun.rs index a4f118a87..a48381f89 100644 --- a/src/imp/to_fun.rs +++ b/src/imp/to_fun.rs @@ -1,10 +1,13 @@ use super::{AssignPattern, Definition, Expr, InPlaceOp, Stmt}; -use crate::{diagnostics::Diagnostics, fun::{ - self, - builtins::{LCONS, LNIL}, - parser::ParseBook, - Book, Name, -}}; +use crate::{ + diagnostics::Diagnostics, + fun::{ + self, + builtins::{LCONS, LNIL}, + parser::ParseBook, + Book, Name, + }, +}; impl ParseBook { // TODO: Change all functions to return diagnostics From cf376afdc165e42963f7c92d64f7959a1ae89687 Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Tue, 6 Aug 2024 17:16:32 -0300 Subject: [PATCH 05/24] Fix tests --- src/diagnostics.rs | 2 +- src/fun/load_book.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 7cfbf9fb1..fab152a97 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -325,7 +325,7 @@ impl Default for DiagnosticsConfig { impl Display for Diagnostic { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match &self.span { - Some(FileSpan { file, .. }) => write!(f, "In {}: \n{}", file, self.message), + Some(FileSpan { file, .. }) => write!(f, "In {} :\n{}", file, self.message), None => write!(f, "{}", self.message), } } diff --git a/src/fun/load_book.rs b/src/fun/load_book.rs index 6ebdd4e8e..cd689063e 100644 --- a/src/fun/load_book.rs +++ b/src/fun/load_book.rs @@ -63,7 +63,7 @@ fn byte_span_to_line(code: &str, span: (usize, usize)) -> TextSpan { let mut end_char = 0; let mut curr_idx = 0; - while curr_idx <= span.0 { + while curr_idx <= span.0 && curr_idx < code.len() { if code.as_bytes()[curr_idx] == b'\n' { start_line += 1; end_line += 1; @@ -74,7 +74,7 @@ fn byte_span_to_line(code: &str, span: (usize, usize)) -> TextSpan { curr_idx += 1; } - while curr_idx <= span.1 { + while curr_idx <= span.1 && curr_idx < code.len() { if code.as_bytes()[curr_idx] == b'\n' { end_line += 1; end_char = 0; From 46b24fce56781965c26d713c5af3362db6502cfe Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Tue, 6 Aug 2024 21:24:33 -0300 Subject: [PATCH 06/24] Fix byte span to line position translation --- src/fun/load_book.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/fun/load_book.rs b/src/fun/load_book.rs index cd689063e..29c3dfa4a 100644 --- a/src/fun/load_book.rs +++ b/src/fun/load_book.rs @@ -57,16 +57,16 @@ fn byte_span_to_line(code: &str, span: (usize, usize)) -> TextSpan { // Will loop for way too long otherwise assert!(span.0 <= span.1); + let code = code.as_bytes(); let mut start_line = 0; let mut start_char = 0; - let mut end_line = 0; - let mut end_char = 0; + let mut end_line; + let mut end_char; let mut curr_idx = 0; - while curr_idx <= span.0 && curr_idx < code.len() { - if code.as_bytes()[curr_idx] == b'\n' { + while curr_idx < span.0 && curr_idx < code.len() { + if code[curr_idx] == b'\n' { start_line += 1; - end_line += 1; start_char = 0; } else { start_char += 1; @@ -74,8 +74,10 @@ fn byte_span_to_line(code: &str, span: (usize, usize)) -> TextSpan { curr_idx += 1; } - while curr_idx <= span.1 && curr_idx < code.len() { - if code.as_bytes()[curr_idx] == b'\n' { + end_line = start_line; + end_char = start_char; + while curr_idx < span.1 && curr_idx < code.len() { + if code[curr_idx] == b'\n' { end_line += 1; end_char = 0; } else { From 9c3eb35b6c64af2e118ba15f52e5e7e8f545ef64 Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Wed, 7 Aug 2024 13:37:07 -0300 Subject: [PATCH 07/24] Report range on unused definition warning --- Cargo.lock | 9 +- Cargo.toml | 8 +- src/diagnostics.rs | 116 ++++++++++++++++++++---- src/fun/load_book.rs | 40 +------- src/fun/mod.rs | 10 +- src/fun/parser.rs | 21 +++-- src/fun/transform/definition_pruning.rs | 8 +- src/fun/transform/desugar_match_defs.rs | 2 +- src/fun/transform/fix_match_terms.rs | 6 +- 9 files changed, 136 insertions(+), 84 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f2dee61e..7d35bad04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,8 +4,9 @@ version = 3 [[package]] name = "TSPL" -version = "0.0.12" -source = "git+https://github.com/HigherOrderCO/TSPL.git?branch=range-info#ae25a5f5e3a805e4ae8854b34b6f29954ec2b68f" +version = "0.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe639519d49b56c98fd4fde7a5a7be01b5563862341a783b9bc2eb58f5120d8b" dependencies = [ "highlight_error", ] @@ -191,8 +192,8 @@ checksum = "809e18805660d7b6b2e2b9f316a5099521b5998d5cba4dda11b5157a21aaef03" [[package]] name = "hvm" -version = "2.0.21" -source = "git+https://github.com/higherorderco/hvm.git?branch=parser-update#01b795d8718cae14c7809316ac7b2acf459b0dba" +version = "2.0.22" +source = "git+https://github.com/HigherOrderCO/hvm.git?branch=parser-update#2a207a6b13aa75704e25d95813082b40b6353ecd" dependencies = [ "TSPL", "cc", diff --git a/Cargo.toml b/Cargo.toml index 4a595ed9e..c7147d065 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,10 +24,10 @@ default = ["cli"] cli = ["dep:clap"] [dependencies] -TSPL = "0.0.12" +TSPL = "0.0.13" clap = { version = "4.4.1", features = ["derive"], optional = true } highlight_error = "0.1.1" -hvm = "2.0.21" +hvm = { git = "https://github.com/HigherOrderCO/hvm.git", branch = "parser-update" } indexmap = "2.2.3" interner = "0.2.1" itertools = "0.11.0" @@ -41,7 +41,3 @@ walkdir = "2.3.3" [profile.test] opt-level = 2 - -[patch.crates-io] -TSPL = { git = "https://github.com/HigherOrderCO/TSPL.git", branch = "range-info" } -hvm = { git = "https://github.com/higherorderco/hvm.git", branch = "parser-update" } diff --git a/src/diagnostics.rs b/src/diagnostics.rs index fab152a97..e613b1b19 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -28,21 +28,6 @@ pub struct DiagnosticsConfig { pub import_shadow: Severity, } -#[derive(Debug, Copy, Clone, Hash)] -pub struct TextLocation { - pub line: usize, - pub char: usize, -} - -pub type TextSpan = (TextLocation, TextLocation); - -#[derive(Debug, Clone, Hash)] -pub struct FileSpan { - pub span: TextSpan, - // Storing files as Strings, could be done as file IDs in the future - pub file: String, -} - #[derive(Debug, Clone)] pub struct Diagnostic { pub message: String, @@ -113,12 +98,18 @@ impl Diagnostics { self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Inet(def_name), None); } - pub fn add_rule_warning(&mut self, warn: impl std::fmt::Display, warn_type: WarningType, def_name: Name) { + pub fn add_rule_warning( + &mut self, + warn: impl std::fmt::Display, + warn_type: WarningType, + def_name: Name, + span: Option, + ) { let severity = self.config.warning_severity(warn_type); if severity == Severity::Error { self.err_counter += 1; } - self.add_diagnostic(warn, severity, DiagnosticOrigin::Rule(def_name.def_name_from_generated()), None); + self.add_diagnostic(warn, severity, DiagnosticOrigin::Rule(def_name.def_name_from_generated()), span); } pub fn add_book_warning(&mut self, warn: impl std::fmt::Display, warn_type: WarningType) { @@ -330,3 +321,94 @@ impl Display for Diagnostic { } } } + +#[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Ord, Eq)] +pub struct TextLocation { + pub line: usize, + pub char: usize, +} + +impl TextLocation { + pub fn new(line: usize, char: usize) -> Self { + TextLocation { line, char } + } + + pub fn from_byte_loc(code: &str, loc: usize) -> Self { + let code = code.as_bytes(); + let mut line = 0; + let mut char = 0; + let mut curr_idx = 0; + while curr_idx < loc && curr_idx < code.len() { + if code[curr_idx] == b'\n' { + line += 1; + char = 0; + } else { + char += 1; + } + curr_idx += 1; + } + + TextLocation { line, char } + } +} + +#[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Ord, Eq)] +pub struct TextSpan { + pub start: TextLocation, + pub end: TextLocation, +} + +impl TextSpan { + pub fn new(start: TextLocation, end: TextLocation) -> Self { + TextSpan { start, end } + } + + pub fn from_byte_span(code: &str, span: (usize, usize)) -> Self { + // Will loop for way too long otherwise + assert!(span.0 <= span.1); + + let code = code.as_bytes(); + let mut start_line = 0; + let mut start_char = 0; + let mut end_line; + let mut end_char; + + let mut curr_idx = 0; + while curr_idx < span.0 && curr_idx < code.len() { + if code[curr_idx] == b'\n' { + start_line += 1; + start_char = 0; + } else { + start_char += 1; + } + curr_idx += 1; + } + + end_line = start_line; + end_char = start_char; + while curr_idx < span.1 && curr_idx < code.len() { + if code[curr_idx] == b'\n' { + end_line += 1; + end_char = 0; + } else { + end_char += 1; + } + curr_idx += 1; + } + + TextSpan::new(TextLocation::new(start_line, start_char), TextLocation::new(end_line, end_char)) + } +} + +#[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Ord, Eq)] +pub struct FileSpan { + pub span: TextSpan, + // Storing files as Strings, could be done as file IDs in the future + pub file: String, +} + +impl FileSpan { + pub fn new(span: TextSpan, origin: &str) -> Self { + FileSpan { span, file: origin.into() } + } +} diff --git a/src/fun/load_book.rs b/src/fun/load_book.rs index 29c3dfa4a..87a8eb7bd 100644 --- a/src/fun/load_book.rs +++ b/src/fun/load_book.rs @@ -3,7 +3,7 @@ use super::{ Book, Name, }; use crate::{ - diagnostics::{Diagnostics, DiagnosticsConfig, FileSpan, TextLocation, TextSpan}, + diagnostics::{Diagnostics, DiagnosticsConfig, FileSpan, TextSpan}, imports::PackageLoader, }; use std::path::Path; @@ -43,7 +43,7 @@ pub fn do_parse_book(code: &str, origin: &Path, mut book: ParseBook) -> Result

Result

Result { do_parse_book(code, origin, ParseBook::builtins())?.to_fun() } - -fn byte_span_to_line(code: &str, span: (usize, usize)) -> TextSpan { - // Will loop for way too long otherwise - assert!(span.0 <= span.1); - - let code = code.as_bytes(); - let mut start_line = 0; - let mut start_char = 0; - let mut end_line; - let mut end_char; - - let mut curr_idx = 0; - while curr_idx < span.0 && curr_idx < code.len() { - if code[curr_idx] == b'\n' { - start_line += 1; - start_char = 0; - } else { - start_char += 1; - } - curr_idx += 1; - } - - end_line = start_line; - end_char = start_char; - while curr_idx < span.1 && curr_idx < code.len() { - if code[curr_idx] == b'\n' { - end_line += 1; - end_char = 0; - } else { - end_char += 1; - } - curr_idx += 1; - } - - (TextLocation { line: start_line, char: start_char }, TextLocation { line: end_line, char: end_char }) -} diff --git a/src/fun/mod.rs b/src/fun/mod.rs index 5d7c687e6..88b983459 100644 --- a/src/fun/mod.rs +++ b/src/fun/mod.rs @@ -1,16 +1,12 @@ use crate::{ - diagnostics::{Diagnostics, DiagnosticsConfig}, + diagnostics::{Diagnostics, DiagnosticsConfig, TextSpan}, imports::Import, maybe_grow, multi_iterator, ENTRY_POINT, }; use indexmap::{IndexMap, IndexSet}; use interner::global::{GlobalPool, GlobalString}; use itertools::Itertools; -use std::{ - borrow::Cow, - hash::Hash, - ops::{Deref, Range}, -}; +use std::{borrow::Cow, hash::Hash, ops::Deref}; pub mod builtins; pub mod check; @@ -78,7 +74,7 @@ pub enum Source { /// Was generated by the compiler. Generated, /// Source code location from the current book. - Local(Range), + Local(TextSpan), /// Imported from another package. Imported, } diff --git a/src/fun/parser.rs b/src/fun/parser.rs index c04d81518..de36e734e 100644 --- a/src/fun/parser.rs +++ b/src/fun/parser.rs @@ -1,6 +1,7 @@ use std::ops::Range; use crate::{ + diagnostics::{TextLocation, TextSpan}, fun::{ display::DisplayFn, Adt, Adts, Constructors, CtrField, FanKind, HvmDefinition, HvmDefinitions, MatchRule, Name, Num, Op, Pattern, Rule, Source, Tag, Term, STRINGS, @@ -164,7 +165,8 @@ impl<'a> TermParser<'a> { self.index = rewind_index; let (nam, ctrs) = self.parse_datatype()?; let end_idx = *self.index(); - let source = if builtin { Source::Builtin } else { Source::Local(ini_idx..end_idx) }; + let span = TextSpan::from_byte_span(self.input(), (ini_idx, end_idx)); + let source = if builtin { Source::Builtin } else { Source::Local(span) }; let adt = Adt { ctrs, source }; self.add_fun_type(&mut book, nam, adt, ini_idx..end_idx)?; indent = self.advance_newlines()?; @@ -276,7 +278,8 @@ impl<'a> TermParser<'a> { let body = p.parse_net()?; *self.index() = ini_idx + *p.index(); let end_idx = *self.index(); - let source = if builtin { Source::Builtin } else { Source::Local(ini_idx..end_idx) }; + let span = TextSpan::from_byte_span(self.input(), (ini_idx, end_idx)); + let source = if builtin { Source::Builtin } else { Source::Local(span) }; let def = HvmDefinition { name: name.clone(), body, source }; Ok(def) } @@ -650,7 +653,8 @@ impl<'a> TermParser<'a> { if name == "def" { // parse the nxt def term. self.index = nxt_def; - let def = FunDefinition::new(name, rules, Source::Local(nxt_def..*self.index())); + let span = TextSpan::from_byte_span(self.input(), (nxt_def, *self.index())); + let def = FunDefinition::new(name, rules, Source::Local(span)); return Ok(Term::Def { def, nxt: Box::new(self.parse_term()?) }); } if name == cur_name { @@ -668,7 +672,8 @@ impl<'a> TermParser<'a> { } } let nxt = self.parse_term()?; - let def = FunDefinition::new(cur_name, rules, Source::Local(nxt_term..*self.index())); + let span = TextSpan::from_byte_span(self.input(), (nxt_term, *self.index())); + let def = FunDefinition::new(cur_name, rules, Source::Local(span)); return Ok(Term::Def { def, nxt: Box::new(nxt) }); } @@ -934,7 +939,7 @@ impl<'a> TermParser<'a> { (Some(def), Some(last_rule)) if last_rule == name => { def.rules.push(rule); if let Source::Local(s) = &mut def.source { - s.end = span.end; + s.end = TextLocation::from_byte_loc(self.input(), span.end); } } // Trying to add a new rule to a previous definition, coming from a different rule. @@ -950,6 +955,7 @@ impl<'a> TermParser<'a> { // Adding the first rule of a new definition (None, _) => { self.check_top_level_redefinition(name, book, span.clone())?; + let span = TextSpan::from_byte_span(self.input(), (span.start, span.end)); let source = if builtin { Source::Builtin } else { Source::Local(span) }; book.fun_defs.insert(name.clone(), FunDefinition::new(name.clone(), vec![rule], source)); } @@ -965,6 +971,7 @@ impl<'a> TermParser<'a> { builtin: bool, ) -> ParseResult<()> { self.check_top_level_redefinition(&def.name, book, span.clone())?; + let span = TextSpan::from_byte_span(self.input(), (span.start, span.end)); let source = if builtin { Source::Builtin } else { Source::Local(span) }; def.source = source; book.imp_defs.insert(def.name.clone(), def); @@ -985,7 +992,8 @@ impl<'a> TermParser<'a> { builtin: bool, ) -> ParseResult<()> { self.check_type_redefinition(&enum_.name, book, span.clone())?; - let source = if builtin { Source::Builtin } else { Source::Local(span.clone()) }; + let text_span = TextSpan::from_byte_span(self.input(), (span.start, span.end)); + let source = if builtin { Source::Builtin } else { Source::Local(text_span) }; let mut adt = Adt { ctrs: Default::default(), source }; for variant in enum_.variants { self.check_top_level_redefinition(&enum_.name, book, span.clone())?; @@ -1034,6 +1042,7 @@ impl<'a> TermParser<'a> { ) -> ParseResult<()> { self.check_type_redefinition(&obj.name, book, span.clone())?; self.check_top_level_redefinition(&obj.name, book, span.clone())?; + let span = TextSpan::from_byte_span(self.input(), (span.start, span.end)); let source = if builtin { Source::Builtin } else { Source::Local(span) }; let mut adt = Adt { ctrs: Default::default(), source }; book.ctrs.insert(obj.name.clone(), obj.name.clone()); diff --git a/src/fun/transform/definition_pruning.rs b/src/fun/transform/definition_pruning.rs index 11a575802..a1461437d 100644 --- a/src/fun/transform/definition_pruning.rs +++ b/src/fun/transform/definition_pruning.rs @@ -1,5 +1,5 @@ use crate::{ - diagnostics::WarningType, + diagnostics::{FileSpan, WarningType}, fun::{Book, Ctx, Name, Source, Term}, maybe_grow, }; @@ -78,7 +78,11 @@ impl Ctx<'_> { if prune_all { rm_def(self.book, &def); } else if !def.is_generated() && !matches!(src, Source::Generated) { - self.info.add_rule_warning("Definition is unused.", WarningType::UnusedDefinition, def); + let span = match src { + Source::Local(span) => Some(FileSpan::new(span, "TODO")), + _ => None, + }; + self.info.add_rule_warning("Definition is unused.", WarningType::UnusedDefinition, def, span); } } Used::Ctr => { diff --git a/src/fun/transform/desugar_match_defs.rs b/src/fun/transform/desugar_match_defs.rs index 72e147bbc..de6acdec3 100644 --- a/src/fun/transform/desugar_match_defs.rs +++ b/src/fun/transform/desugar_match_defs.rs @@ -25,7 +25,7 @@ impl Ctx<'_> { | DesugarMatchDefErr::NumMissingDefault | DesugarMatchDefErr::TypeMismatch { .. } => self.info.add_rule_error(err, def_name.clone()), DesugarMatchDefErr::RepeatedBind { .. } => { - self.info.add_rule_warning(err, WarningType::RepeatedBind, def_name.clone()) + self.info.add_rule_warning(err, WarningType::RepeatedBind, def_name.clone(), None) } } } diff --git a/src/fun/transform/fix_match_terms.rs b/src/fun/transform/fix_match_terms.rs index 149741198..11adfd5fc 100644 --- a/src/fun/transform/fix_match_terms.rs +++ b/src/fun/transform/fix_match_terms.rs @@ -54,13 +54,13 @@ impl Ctx<'_> { self.info.add_rule_error(err, def.name.clone()) } FixMatchErr::IrrefutableMatch { .. } => { - self.info.add_rule_warning(err, WarningType::IrrefutableMatch, def.name.clone()) + self.info.add_rule_warning(err, WarningType::IrrefutableMatch, def.name.clone(), None) } FixMatchErr::UnreachableMatchArms { .. } => { - self.info.add_rule_warning(err, WarningType::UnreachableMatch, def.name.clone()) + self.info.add_rule_warning(err, WarningType::UnreachableMatch, def.name.clone(), None) } FixMatchErr::RedundantArm { .. } => { - self.info.add_rule_warning(err, WarningType::RedundantMatch, def.name.clone()) + self.info.add_rule_warning(err, WarningType::RedundantMatch, def.name.clone(), None) } } } From 811e5110140afd5a4077c778eb00a2183cd89902 Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Wed, 7 Aug 2024 13:52:08 -0300 Subject: [PATCH 08/24] Optional origin in file span --- src/diagnostics.rs | 11 ++++++----- src/fun/load_book.rs | 2 +- src/fun/transform/definition_pruning.rs | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/diagnostics.rs b/src/diagnostics.rs index e613b1b19..18226e98b 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -316,8 +316,8 @@ impl Default for DiagnosticsConfig { impl Display for Diagnostic { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match &self.span { - Some(FileSpan { file, .. }) => write!(f, "In {} :\n{}", file, self.message), - None => write!(f, "{}", self.message), + Some(FileSpan { file: Some(file), .. }) => write!(f, "In {} :\n{}", file, self.message), + _ => write!(f, "{}", self.message), } } } @@ -404,11 +404,12 @@ impl TextSpan { pub struct FileSpan { pub span: TextSpan, // Storing files as Strings, could be done as file IDs in the future - pub file: String, + // This is currently optional, we might want to change it later + pub file: Option, } impl FileSpan { - pub fn new(span: TextSpan, origin: &str) -> Self { - FileSpan { span, file: origin.into() } + pub fn new(span: TextSpan, origin: Option<&str>) -> Self { + FileSpan { span, file: origin.map(|s| s.into()) } } } diff --git a/src/fun/load_book.rs b/src/fun/load_book.rs index 87a8eb7bd..c850fe287 100644 --- a/src/fun/load_book.rs +++ b/src/fun/load_book.rs @@ -44,7 +44,7 @@ pub fn do_parse_book(code: &str, origin: &Path, mut book: ParseBook) -> Result

{ rm_def(self.book, &def); } else if !def.is_generated() && !matches!(src, Source::Generated) { let span = match src { - Source::Local(span) => Some(FileSpan::new(span, "TODO")), + Source::Local(span) => Some(FileSpan::new(span, None)), _ => None, }; self.info.add_rule_warning("Definition is unused.", WarningType::UnusedDefinition, def, span); From f9198f4b9f015a483291e6a8027e673ee856e159 Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Wed, 7 Aug 2024 16:18:29 -0300 Subject: [PATCH 09/24] Add function to display single diagnostic with its origin --- src/diagnostics.rs | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 18226e98b..a801bfb64 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -236,6 +236,77 @@ impl Diagnostics { Ok(()) }) } + + // pub fn display_with_severity<'a>( + // &'a self, + // severity: Severity, + // origin: &'a DiagnosticOrigin, + // ) -> impl std::fmt::Display + '_ { + // DisplayFn(move |f| { + // fn filter<'a>( + // errs: impl IntoIterator, + // severity: Severity, + // ) -> impl Iterator { + // errs.into_iter().filter(move |err| err.severity == severity) + // } + + // let mut has_msg = false; + // if let Some(errs) = self.diagnostics.get(&origin) { + // let mut errs = filter(errs, severity).peekable(); + // if errs.peek().is_some() { + // match &origin { + // DiagnosticOrigin::Parsing => { + // for err in errs { + // writeln!(f, "{err}")?; + // } + // } + // DiagnosticOrigin::Book => { + // for err in errs { + // writeln!(f, "{err}")?; + // } + // } + // DiagnosticOrigin::Rule(nam) => { + // writeln!(f, "\x1b[1mIn definition '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; + // for err in errs { + // writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; + // } + // } + // DiagnosticOrigin::Inet(nam) => { + // writeln!(f, "\x1b[1mIn compiled inet '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; + // for err in errs { + // writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; + // } + // } + // DiagnosticOrigin::Readback => { + // writeln!(f, "\x1b[1mDuring readback:\x1b[0m")?; + // for err in errs { + // writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; + // } + // } + // } + // has_msg = true; + // } + // } + // if has_msg { + // writeln!(f)?; + // } + // Ok(()) + // }) + // } + + // /// Returns a Display that prints the diagnostics with one of the given severities. + // pub fn display_all_with_severity(&self, severity: Severity) -> impl std::fmt::Display + '_ { + // DisplayFn(move |f| { + // let mut has_msg = false; + // for orig in self.diagnostics.keys() { + // write!(f, "{}", self.display_with_severity(severity, orig))?; + // } + // if has_msg { + // writeln!(f)?; + // } + // Ok(()) + // }) + // } } impl Display for Diagnostics { @@ -322,6 +393,30 @@ impl Display for Diagnostic { } } +impl Diagnostic { + pub fn display_with_origin<'a>(&'a self, origin: &'a DiagnosticOrigin) -> impl std::fmt::Display + '_ { + DisplayFn(move |f| { + match origin { + DiagnosticOrigin::Parsing => writeln!(f, "{self}")?, + DiagnosticOrigin::Book => writeln!(f, "{self}")?, + DiagnosticOrigin::Rule(nam) => { + writeln!(f, "\x1b[1mIn definition '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; + writeln!(f, "{:ERR_INDENT_SIZE$}{self}", "")?; + } + DiagnosticOrigin::Inet(nam) => { + writeln!(f, "\x1b[1mIn compiled inet '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; + writeln!(f, "{:ERR_INDENT_SIZE$}{self}", "")?; + } + DiagnosticOrigin::Readback => { + writeln!(f, "\x1b[1mDuring readback:\x1b[0m")?; + writeln!(f, "{:ERR_INDENT_SIZE$}{self}", "")?; + } + }; + Ok(()) + }) + } +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Ord, Eq)] pub struct TextLocation { pub line: usize, From 1fe3dd174d176aa2e5ee9acf27b8955006084ea7 Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Fri, 9 Aug 2024 17:54:03 -0300 Subject: [PATCH 10/24] Bump HVM version to 2.0.22 --- Cargo.lock | 3 ++- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d35bad04..890183d65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -193,7 +193,8 @@ checksum = "809e18805660d7b6b2e2b9f316a5099521b5998d5cba4dda11b5157a21aaef03" [[package]] name = "hvm" version = "2.0.22" -source = "git+https://github.com/HigherOrderCO/hvm.git?branch=parser-update#2a207a6b13aa75704e25d95813082b40b6353ecd" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fafa02949c005e70869074ac9db489ad92eaf92c78b4dcf6c0b45d98982c08d" dependencies = [ "TSPL", "cc", diff --git a/Cargo.toml b/Cargo.toml index c7147d065..9ee239bc9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ cli = ["dep:clap"] TSPL = "0.0.13" clap = { version = "4.4.1", features = ["derive"], optional = true } highlight_error = "0.1.1" -hvm = { git = "https://github.com/HigherOrderCO/hvm.git", branch = "parser-update" } +hvm = "2.0.22" indexmap = "2.2.3" interner = "0.2.1" itertools = "0.11.0" From f1d419d0d1329ac63d4ad8952ebd94c5f62bdd93 Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Tue, 13 Aug 2024 13:33:42 -0300 Subject: [PATCH 11/24] Remove unused diagnostics code --- src/diagnostics.rs | 71 ---------------------------------------------- 1 file changed, 71 deletions(-) diff --git a/src/diagnostics.rs b/src/diagnostics.rs index a801bfb64..7f355fd17 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -236,77 +236,6 @@ impl Diagnostics { Ok(()) }) } - - // pub fn display_with_severity<'a>( - // &'a self, - // severity: Severity, - // origin: &'a DiagnosticOrigin, - // ) -> impl std::fmt::Display + '_ { - // DisplayFn(move |f| { - // fn filter<'a>( - // errs: impl IntoIterator, - // severity: Severity, - // ) -> impl Iterator { - // errs.into_iter().filter(move |err| err.severity == severity) - // } - - // let mut has_msg = false; - // if let Some(errs) = self.diagnostics.get(&origin) { - // let mut errs = filter(errs, severity).peekable(); - // if errs.peek().is_some() { - // match &origin { - // DiagnosticOrigin::Parsing => { - // for err in errs { - // writeln!(f, "{err}")?; - // } - // } - // DiagnosticOrigin::Book => { - // for err in errs { - // writeln!(f, "{err}")?; - // } - // } - // DiagnosticOrigin::Rule(nam) => { - // writeln!(f, "\x1b[1mIn definition '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; - // for err in errs { - // writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; - // } - // } - // DiagnosticOrigin::Inet(nam) => { - // writeln!(f, "\x1b[1mIn compiled inet '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; - // for err in errs { - // writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; - // } - // } - // DiagnosticOrigin::Readback => { - // writeln!(f, "\x1b[1mDuring readback:\x1b[0m")?; - // for err in errs { - // writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; - // } - // } - // } - // has_msg = true; - // } - // } - // if has_msg { - // writeln!(f)?; - // } - // Ok(()) - // }) - // } - - // /// Returns a Display that prints the diagnostics with one of the given severities. - // pub fn display_all_with_severity(&self, severity: Severity) -> impl std::fmt::Display + '_ { - // DisplayFn(move |f| { - // let mut has_msg = false; - // for orig in self.diagnostics.keys() { - // write!(f, "{}", self.display_with_severity(severity, orig))?; - // } - // if has_msg { - // writeln!(f)?; - // } - // Ok(()) - // }) - // } } impl Display for Diagnostics { From 4e155ccce6dd928f2328fe15e9b26db5620650cc Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Tue, 13 Aug 2024 23:04:41 -0300 Subject: [PATCH 12/24] Implement function diagnostic origin --- src/diagnostics.rs | 53 +++++++++++++--- src/fun/load_book.rs | 2 +- src/fun/parser.rs | 16 ++--- src/imp/to_fun.rs | 62 +++++++++++-------- ..._file__mismatched_ask_statements.bend.snap | 3 +- 5 files changed, 92 insertions(+), 44 deletions(-) diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 7f355fd17..5f398d5f5 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -4,6 +4,7 @@ use crate::fun::{display::DisplayFn, Name}; use std::{ collections::BTreeMap, fmt::{Display, Formatter}, + ops::Range, }; pub const ERR_INDENT_SIZE: usize = 2; @@ -43,6 +44,8 @@ pub enum DiagnosticOrigin { Book, /// An error in a pattern-matching function definition rule. Rule(Name), + /// An error when transforming `imp` syntax into `fun`. + Function(Name), /// An error in a compiled inet. Inet(String), /// An error during readback of hvm-core run results. @@ -83,13 +86,18 @@ impl Diagnostics { self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Book, None); } - pub fn add_rule_error(&mut self, err: impl std::fmt::Display, def_name: Name) { + pub fn add_rule_error(&mut self, err: impl std::fmt::Display, name: Name) { + self.err_counter += 1; + self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Rule(name.def_name_from_generated()), None); + } + + pub fn add_function_error(&mut self, err: impl std::fmt::Display, name: Name, span: Option) { self.err_counter += 1; self.add_diagnostic( err, Severity::Error, - DiagnosticOrigin::Rule(def_name.def_name_from_generated()), - None, + DiagnosticOrigin::Function(name.def_name_from_generated()), + span, ); } @@ -122,7 +130,7 @@ impl Diagnostics { pub fn add_diagnostic( &mut self, - msg: impl ToString, + msg: impl std::fmt::Display, severity: Severity, orig: DiagnosticOrigin, range: Option, @@ -214,6 +222,12 @@ impl Diagnostics { writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; } } + DiagnosticOrigin::Function(nam) => { + writeln!(f, "\x1b[1mIn function '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; + for err in errs { + writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; + } + } DiagnosticOrigin::Inet(nam) => { writeln!(f, "\x1b[1mIn compiled inet '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; for err in errs { @@ -236,6 +250,15 @@ impl Diagnostics { Ok(()) }) } + + pub fn display_only_messages(&self) -> impl std::fmt::Display + '_ { + DisplayFn(move |f| { + for err in self.diagnostics.values().flatten() { + writeln!(f, "{err}")?; + } + Ok(()) + }) + } } impl Display for Diagnostics { @@ -263,11 +286,15 @@ impl From for Diagnostics { } impl From for Diagnostics { + /// Transforms a parse error into `Diagnostics`. + /// + /// NOTE: Since `ParseError` does not include the source code, we can't get the `TextLocation` of the error, + /// so it is not included in the diagnostic. + /// range is set as None. fn from(value: ParseError) -> Self { Self { diagnostics: BTreeMap::from_iter([( DiagnosticOrigin::Parsing, - // TODO: range is not because we're missing the origin file, can we fix this? vec![Diagnostic { message: value.into(), severity: Severity::Error, span: None }], )]), ..Default::default() @@ -315,6 +342,8 @@ impl Default for DiagnosticsConfig { impl Display for Diagnostic { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + // TODO: this could be problematic when printing multiple errors from the same file + // currently, there shouldn't be any `Diagnostics` with multiple problems `FileSpan`s match &self.span { Some(FileSpan { file: Some(file), .. }) => write!(f, "In {} :\n{}", file, self.message), _ => write!(f, "{}", self.message), @@ -332,6 +361,10 @@ impl Diagnostic { writeln!(f, "\x1b[1mIn definition '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; writeln!(f, "{:ERR_INDENT_SIZE$}{self}", "")?; } + DiagnosticOrigin::Function(nam) => { + writeln!(f, "\x1b[1mIn function '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; + writeln!(f, "{:ERR_INDENT_SIZE$}{self}", "")?; + } DiagnosticOrigin::Inet(nam) => { writeln!(f, "\x1b[1mIn compiled inet '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; writeln!(f, "{:ERR_INDENT_SIZE$}{self}", "")?; @@ -357,6 +390,7 @@ impl TextLocation { TextLocation { line, char } } + /// Transforms a `usize` byte index on `code` into a `TextLocation`. pub fn from_byte_loc(code: &str, loc: usize) -> Self { let code = code.as_bytes(); let mut line = 0; @@ -387,9 +421,10 @@ impl TextSpan { TextSpan { start, end } } - pub fn from_byte_span(code: &str, span: (usize, usize)) -> Self { + /// Transforms a `usize` byte range on `code` into a `TextLocation`. + pub fn from_byte_span(code: &str, span: Range) -> Self { // Will loop for way too long otherwise - assert!(span.0 <= span.1); + assert!(span.start <= span.end); let code = code.as_bytes(); let mut start_line = 0; @@ -398,7 +433,7 @@ impl TextSpan { let mut end_char; let mut curr_idx = 0; - while curr_idx < span.0 && curr_idx < code.len() { + while curr_idx < span.start && curr_idx < code.len() { if code[curr_idx] == b'\n' { start_line += 1; start_char = 0; @@ -410,7 +445,7 @@ impl TextSpan { end_line = start_line; end_char = start_char; - while curr_idx < span.1 && curr_idx < code.len() { + while curr_idx < span.end && curr_idx < code.len() { if code[curr_idx] == b'\n' { end_line += 1; end_char = 0; diff --git a/src/fun/load_book.rs b/src/fun/load_book.rs index c850fe287..41018a17a 100644 --- a/src/fun/load_book.rs +++ b/src/fun/load_book.rs @@ -43,7 +43,7 @@ pub fn do_parse_book(code: &str, origin: &Path, mut book: ParseBook) -> Result

TermParser<'a> { self.index = rewind_index; let (nam, ctrs) = self.parse_datatype()?; let end_idx = *self.index(); - let span = TextSpan::from_byte_span(self.input(), (ini_idx, end_idx)); + let span = TextSpan::from_byte_span(self.input(), ini_idx..end_idx); let source = if builtin { Source::Builtin } else { Source::Local(span) }; let adt = Adt { ctrs, source }; self.add_fun_type(&mut book, nam, adt, ini_idx..end_idx)?; @@ -278,7 +278,7 @@ impl<'a> TermParser<'a> { let body = p.parse_net()?; *self.index() = ini_idx + *p.index(); let end_idx = *self.index(); - let span = TextSpan::from_byte_span(self.input(), (ini_idx, end_idx)); + let span = TextSpan::from_byte_span(self.input(), ini_idx..end_idx); let source = if builtin { Source::Builtin } else { Source::Local(span) }; let def = HvmDefinition { name: name.clone(), body, source }; Ok(def) @@ -653,7 +653,7 @@ impl<'a> TermParser<'a> { if name == "def" { // parse the nxt def term. self.index = nxt_def; - let span = TextSpan::from_byte_span(self.input(), (nxt_def, *self.index())); + let span = TextSpan::from_byte_span(self.input(), nxt_def..*self.index()); let def = FunDefinition::new(name, rules, Source::Local(span)); return Ok(Term::Def { def, nxt: Box::new(self.parse_term()?) }); } @@ -672,7 +672,7 @@ impl<'a> TermParser<'a> { } } let nxt = self.parse_term()?; - let span = TextSpan::from_byte_span(self.input(), (nxt_term, *self.index())); + let span = TextSpan::from_byte_span(self.input(), nxt_term..*self.index()); let def = FunDefinition::new(cur_name, rules, Source::Local(span)); return Ok(Term::Def { def, nxt: Box::new(nxt) }); } @@ -955,7 +955,7 @@ impl<'a> TermParser<'a> { // Adding the first rule of a new definition (None, _) => { self.check_top_level_redefinition(name, book, span.clone())?; - let span = TextSpan::from_byte_span(self.input(), (span.start, span.end)); + let span = TextSpan::from_byte_span(self.input(), span.start..span.end); let source = if builtin { Source::Builtin } else { Source::Local(span) }; book.fun_defs.insert(name.clone(), FunDefinition::new(name.clone(), vec![rule], source)); } @@ -971,7 +971,7 @@ impl<'a> TermParser<'a> { builtin: bool, ) -> ParseResult<()> { self.check_top_level_redefinition(&def.name, book, span.clone())?; - let span = TextSpan::from_byte_span(self.input(), (span.start, span.end)); + let span = TextSpan::from_byte_span(self.input(), span.start..span.end); let source = if builtin { Source::Builtin } else { Source::Local(span) }; def.source = source; book.imp_defs.insert(def.name.clone(), def); @@ -992,7 +992,7 @@ impl<'a> TermParser<'a> { builtin: bool, ) -> ParseResult<()> { self.check_type_redefinition(&enum_.name, book, span.clone())?; - let text_span = TextSpan::from_byte_span(self.input(), (span.start, span.end)); + let text_span = TextSpan::from_byte_span(self.input(), span.start..span.end); let source = if builtin { Source::Builtin } else { Source::Local(text_span) }; let mut adt = Adt { ctrs: Default::default(), source }; for variant in enum_.variants { @@ -1042,7 +1042,7 @@ impl<'a> TermParser<'a> { ) -> ParseResult<()> { self.check_type_redefinition(&obj.name, book, span.clone())?; self.check_top_level_redefinition(&obj.name, book, span.clone())?; - let span = TextSpan::from_byte_span(self.input(), (span.start, span.end)); + let span = TextSpan::from_byte_span(self.input(), span.start..span.end); let source = if builtin { Source::Builtin } else { Source::Local(span) }; let mut adt = Adt { ctrs: Default::default(), source }; book.ctrs.insert(obj.name.clone(), obj.name.clone()); diff --git a/src/imp/to_fun.rs b/src/imp/to_fun.rs index a48381f89..5ecd33ec5 100644 --- a/src/imp/to_fun.rs +++ b/src/imp/to_fun.rs @@ -1,11 +1,11 @@ use super::{AssignPattern, Definition, Expr, InPlaceOp, Stmt}; use crate::{ - diagnostics::Diagnostics, + diagnostics::{Diagnostics, FileSpan}, fun::{ self, builtins::{LCONS, LNIL}, parser::ParseBook, - Book, Name, + Book, Name, Source, }, }; @@ -29,12 +29,24 @@ impl ParseBook { } impl Definition { - pub fn to_fun(self) -> Result { - let body = self.body.into_fun().map_err(|e| format!("In function '{}': {}", self.name, e))?; + pub fn to_fun(self) -> Result { + let span = match self.source { + Source::Local(span) => Some(FileSpan::new(span, None)), + _ => None, + }; + + let body = self.body.into_fun().map_err(|e| { + let mut diags = Diagnostics::default(); + diags.add_function_error(e.display_only_messages(), self.name.clone(), span.clone()); + diags + })?; + let body = match body { StmtToFun::Return(term) => term, StmtToFun::Assign(..) => { - return Err(format!("Function '{}' doesn't end with a return statement", self.name)); + let mut diags = Diagnostics::default(); + diags.add_function_error("Function doesn't end with a return statement", self.name, span); + return Err(diags); } }; @@ -71,7 +83,7 @@ enum StmtToFun { Assign(bool, fun::Pattern, fun::Term), } -fn take(t: Stmt) -> Result<(bool, Option, fun::Term), String> { +fn take(t: Stmt) -> Result<(bool, Option, fun::Term), Diagnostics> { match t.into_fun()? { StmtToFun::Return(ret) => Ok((false, None, ret)), StmtToFun::Assign(x, pat, val) => Ok((x, Some(pat), val)), @@ -87,7 +99,7 @@ fn wrap(nxt: Option, term: fun::Term, ask: bool) -> StmtToFun { } impl Stmt { - fn into_fun(self) -> Result { + fn into_fun(self) -> Result { // TODO: Refactor this to not repeat everything. // TODO: When we have an error with an assignment, we should show the offending assignment (eg. "{pat} = ..."). let stmt_to_fun = match self { @@ -104,7 +116,7 @@ impl Stmt { wrap(nxt_pat, term, ask) } Stmt::Assign { pat: AssignPattern::MapSet(..), val: _, nxt: None } => { - return Err("Branch ends with map assignment.".to_string()); + return Err("Branch ends with map assignment.".to_string())?; } Stmt::Assign { pat, val, nxt: Some(nxt) } => { let pat = pat.into_fun(); @@ -183,17 +195,17 @@ impl Stmt { (ask && ask_, Some(tp), t, e) } (StmtToFun::Assign(..), StmtToFun::Assign(..)) => { - return Err("'if' branches end with different assignments.".to_string()); + return Err("'if' branches end with different assignments.".to_string())?; } (StmtToFun::Return(..), StmtToFun::Assign(..)) => { return Err( "Expected 'else' branch from 'if' to return, but it ends with assignment.".to_string(), - ); + )?; } (StmtToFun::Assign(..), StmtToFun::Return(..)) => { return Err( "Expected 'else' branch from 'if' to end with assignment, but it returns.".to_string(), - ); + )?; } }; let arms = vec![else_, then]; @@ -219,13 +231,13 @@ impl Stmt { let (arm_ask, arm_pat, arm_rgt) = take(arm.rgt)?; match (&arm_pat, &fst_pat) { (Some(arm_pat), Some(fst_pat)) if arm_pat != fst_pat || arm_ask != fst_ask => { - return Err("'match' arms end with different assignments.".to_string()); + return Err("'match' arms end with different assignments.".to_string())?; } (Some(_), None) => { - return Err("Expected 'match' arms to end with assignment, but it returns.".to_string()); + return Err("Expected 'match' arms to end with assignment, but it returns.".to_string())?; } (None, Some(_)) => { - return Err("Expected 'match' arms to return, but it ends with assignment.".to_string()); + return Err("Expected 'match' arms to return, but it ends with assignment.".to_string())?; } (Some(_), Some(_)) => fun_arms.push((arm.lft, vec![], arm_rgt)), (None, None) => fun_arms.push((arm.lft, vec![], arm_rgt)), @@ -246,13 +258,13 @@ impl Stmt { let (arm_ask, arm_pat, arm) = take(arm)?; match (&arm_pat, &fst_pat) { (Some(arm_pat), Some(fst_pat)) if arm_pat != fst_pat || arm_ask != fst_ask => { - return Err("'switch' arms end with different assignments.".to_string()); + return Err("'switch' arms end with different assignments.".to_string())?; } (Some(_), None) => { - return Err("Expected 'switch' arms to end with assignment, but it returns.".to_string()); + return Err("Expected 'switch' arms to end with assignment, but it returns.".to_string())?; } (None, Some(_)) => { - return Err("Expected 'switch' arms to return, but it ends with assignment.".to_string()); + return Err("Expected 'switch' arms to return, but it ends with assignment.".to_string())?; } (Some(_), Some(_)) => fun_arms.push(arm), (None, None) => fun_arms.push(arm), @@ -274,13 +286,13 @@ impl Stmt { let (arm_ask, arm_pat, arm_rgt) = take(arm.rgt)?; match (&arm_pat, &fst_pat) { (Some(arm_pat), Some(fst_pat)) if arm_pat != fst_pat || arm_ask != fst_ask => { - return Err("'fold' arms end with different assignments.".to_string()); + return Err("'fold' arms end with different assignments.".to_string())?; } (Some(_), None) => { - return Err("Expected 'fold' arms to end with assignment, but it returns.".to_string()); + return Err("Expected 'fold' arms to end with assignment, but it returns.".to_string())?; } (None, Some(_)) => { - return Err("Expected 'fold' arms to return, but it ends with assignment.".to_string()); + return Err("Expected 'fold' arms to return, but it ends with assignment.".to_string())?; } (Some(_), Some(_)) => fun_arms.push((arm.lft, vec![], arm_rgt)), (None, None) => fun_arms.push((arm.lft, vec![], arm_rgt)), @@ -298,17 +310,17 @@ impl Stmt { (aa && ba, Some(sp), s, b) } (StmtToFun::Assign(..), StmtToFun::Assign(..)) => { - return Err("'bend' branches end with different assignments.".to_string()); + return Err("'bend' branches end with different assignments.".to_string())?; } (StmtToFun::Return(..), StmtToFun::Assign(..)) => { return Err( "Expected 'else' branch from 'bend' to return, but it ends with assignment.".to_string(), - ); + )?; } (StmtToFun::Assign(..), StmtToFun::Return(..)) => { return Err( "Expected 'else' branch from 'bend' to end with assignment, but it returns.".to_string(), - ); + )?; } }; let term = @@ -459,7 +471,7 @@ fn wrap_nxt_assign_stmt( nxt: Option>, pat: Option, ask: bool, -) -> Result { +) -> Result { if let Some(nxt) = nxt { if let Some(pat) = pat { let (ask_nxt, nxt_pat, nxt) = take(*nxt)?; @@ -470,7 +482,7 @@ fn wrap_nxt_assign_stmt( }; Ok(wrap(nxt_pat, term, ask_nxt)) } else { - Err("Statement ends with return but is not at end of function.".to_string()) + Err("Statement ends with return but is not at end of function.".to_string())? } } else if let Some(pat) = pat { Ok(StmtToFun::Assign(ask, pat, term)) diff --git a/tests/snapshots/compile_file__mismatched_ask_statements.bend.snap b/tests/snapshots/compile_file__mismatched_ask_statements.bend.snap index 57957a02e..6053c2c78 100644 --- a/tests/snapshots/compile_file__mismatched_ask_statements.bend.snap +++ b/tests/snapshots/compile_file__mismatched_ask_statements.bend.snap @@ -3,4 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/mismatched_ask_statements.bend --- Errors: -In function 'main': 'match' arms end with different assignments. +In function 'main': + 'match' arms end with different assignments. From c9c721970c9a9dc45c5f83e9bb180cc125dfc5c1 Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Wed, 14 Aug 2024 10:00:32 -0300 Subject: [PATCH 13/24] Add word to cspell --- cspell.json | 1 + 1 file changed, 1 insertion(+) diff --git a/cspell.json b/cspell.json index 4aa80d973..e722b5b27 100644 --- a/cspell.json +++ b/cspell.json @@ -21,6 +21,7 @@ "concat", "ctrs", "cuda", + "curr", "datatypes", "Deque", "destructures", From ca4da8fd068cb022f1df67383e0874d77030626b Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Wed, 14 Aug 2024 13:33:20 -0300 Subject: [PATCH 14/24] Remove `Rule` diagnostic origin in favor of `Function` --- cspell.json | 1 - src/diagnostics.rs | 59 +++++++------------ src/fun/check/unbound_refs.rs | 6 +- src/fun/check/unbound_vars.rs | 2 +- src/fun/mod.rs | 7 +++ src/fun/transform/apply_args.rs | 6 +- src/fun/transform/definition_pruning.rs | 13 ++-- src/fun/transform/desugar_bend.rs | 2 +- src/fun/transform/desugar_fold.rs | 2 +- src/fun/transform/desugar_match_defs.rs | 11 +++- src/fun/transform/desugar_open.rs | 2 +- src/fun/transform/desugar_with_blocks.rs | 2 +- src/fun/transform/fix_match_defs.rs | 2 +- src/fun/transform/fix_match_terms.rs | 29 +++++---- src/hvm/check_net_size.rs | 3 +- src/imp/to_fun.rs | 17 +++--- ..._file__mismatched_ask_statements.bend.snap | 2 +- 17 files changed, 89 insertions(+), 77 deletions(-) diff --git a/cspell.json b/cspell.json index e722b5b27..4aa80d973 100644 --- a/cspell.json +++ b/cspell.json @@ -21,7 +21,6 @@ "concat", "ctrs", "cuda", - "curr", "datatypes", "Deque", "destructures", diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 5f398d5f5..6607e557d 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -1,6 +1,6 @@ use TSPL::ParseError; -use crate::fun::{display::DisplayFn, Name}; +use crate::fun::{display::DisplayFn, Name, Source}; use std::{ collections::BTreeMap, fmt::{Display, Formatter}, @@ -42,9 +42,7 @@ pub enum DiagnosticOrigin { Parsing, /// An error from the relationship between multiple top-level definitions. Book, - /// An error in a pattern-matching function definition rule. - Rule(Name), - /// An error when transforming `imp` syntax into `fun`. + /// An error in a function definition. Function(Name), /// An error in a compiled inet. Inet(String), @@ -86,13 +84,9 @@ impl Diagnostics { self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Book, None); } - pub fn add_rule_error(&mut self, err: impl std::fmt::Display, name: Name) { - self.err_counter += 1; - self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Rule(name.def_name_from_generated()), None); - } - - pub fn add_function_error(&mut self, err: impl std::fmt::Display, name: Name, span: Option) { + pub fn add_function_error(&mut self, err: impl std::fmt::Display, name: Name, source: Option<&Source>) { self.err_counter += 1; + let span = source.and_then(|src| src.span()).map(|s| FileSpan::new(s, None)); self.add_diagnostic( err, Severity::Error, @@ -106,18 +100,19 @@ impl Diagnostics { self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Inet(def_name), None); } - pub fn add_rule_warning( + pub fn add_function_warning( &mut self, warn: impl std::fmt::Display, warn_type: WarningType, def_name: Name, - span: Option, + source: Option<&Source>, ) { let severity = self.config.warning_severity(warn_type); if severity == Severity::Error { self.err_counter += 1; } - self.add_diagnostic(warn, severity, DiagnosticOrigin::Rule(def_name.def_name_from_generated()), span); + let span = source.and_then(|src| src.span()).map(|s| FileSpan::new(s, None)); + self.add_diagnostic(warn, severity, DiagnosticOrigin::Function(def_name.def_name_from_generated()), span); } pub fn add_book_warning(&mut self, warn: impl std::fmt::Display, warn_type: WarningType) { @@ -147,7 +142,7 @@ impl Diagnostics { match result { Ok(t) => Some(t), Err(e) => { - self.add_rule_error(e, def_name); + self.add_function_error(e, def_name, None); None } } @@ -216,14 +211,8 @@ impl Diagnostics { writeln!(f, "{err}")?; } } - DiagnosticOrigin::Rule(nam) => { - writeln!(f, "\x1b[1mIn definition '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; - for err in errs { - writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; - } - } DiagnosticOrigin::Function(nam) => { - writeln!(f, "\x1b[1mIn function '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; + writeln!(f, "\x1b[1mIn definition '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; for err in errs { writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; } @@ -357,12 +346,8 @@ impl Diagnostic { match origin { DiagnosticOrigin::Parsing => writeln!(f, "{self}")?, DiagnosticOrigin::Book => writeln!(f, "{self}")?, - DiagnosticOrigin::Rule(nam) => { - writeln!(f, "\x1b[1mIn definition '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; - writeln!(f, "{:ERR_INDENT_SIZE$}{self}", "")?; - } DiagnosticOrigin::Function(nam) => { - writeln!(f, "\x1b[1mIn function '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; + writeln!(f, "\x1b[1mIn definition '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; writeln!(f, "{:ERR_INDENT_SIZE$}{self}", "")?; } DiagnosticOrigin::Inet(nam) => { @@ -395,15 +380,15 @@ impl TextLocation { let code = code.as_bytes(); let mut line = 0; let mut char = 0; - let mut curr_idx = 0; - while curr_idx < loc && curr_idx < code.len() { - if code[curr_idx] == b'\n' { + let mut cur_idx = 0; + while cur_idx < loc && cur_idx < code.len() { + if code[cur_idx] == b'\n' { line += 1; char = 0; } else { char += 1; } - curr_idx += 1; + cur_idx += 1; } TextLocation { line, char } @@ -432,27 +417,27 @@ impl TextSpan { let mut end_line; let mut end_char; - let mut curr_idx = 0; - while curr_idx < span.start && curr_idx < code.len() { - if code[curr_idx] == b'\n' { + let mut cur_idx = 0; + while cur_idx < span.start && cur_idx < code.len() { + if code[cur_idx] == b'\n' { start_line += 1; start_char = 0; } else { start_char += 1; } - curr_idx += 1; + cur_idx += 1; } end_line = start_line; end_char = start_char; - while curr_idx < span.end && curr_idx < code.len() { - if code[curr_idx] == b'\n' { + while cur_idx < span.end && cur_idx < code.len() { + if code[cur_idx] == b'\n' { end_line += 1; end_char = 0; } else { end_char += 1; } - curr_idx += 1; + cur_idx += 1; } TextSpan::new(TextLocation::new(start_line, start_char), TextLocation::new(end_line, end_char)) diff --git a/src/fun/check/unbound_refs.rs b/src/fun/check/unbound_refs.rs index 837ace1c8..7a7f11ab8 100644 --- a/src/fun/check/unbound_refs.rs +++ b/src/fun/check/unbound_refs.rs @@ -14,7 +14,11 @@ impl Ctx<'_> { rule.body.check_unbound_refs(self.book, &mut unbounds); } for unbound in unbounds { - self.info.add_rule_error(format!("Reference to undefined function '{unbound}'"), def.name.clone()); + self.info.add_function_error( + format!("Reference to undefined function '{unbound}'"), + def.name.clone(), + Some(&def.source), + ); } } self.info.fatal(()) diff --git a/src/fun/check/unbound_vars.rs b/src/fun/check/unbound_vars.rs index cae0620d5..b6fe34a40 100644 --- a/src/fun/check/unbound_vars.rs +++ b/src/fun/check/unbound_vars.rs @@ -28,7 +28,7 @@ impl Ctx<'_> { } for err in errs { - self.info.add_rule_error(err, def_name.clone()); + self.info.add_function_error(err, def_name.clone(), Some(&def.source)); } } diff --git a/src/fun/mod.rs b/src/fun/mod.rs index 88b983459..1f42c7b72 100644 --- a/src/fun/mod.rs +++ b/src/fun/mod.rs @@ -1123,6 +1123,13 @@ impl Source { pub fn is_local(&self) -> bool { matches!(self, Source::Local(..)) } + + pub fn span(&self) -> Option { + match self { + Source::Local(span) => Some(*span), + _ => None, + } + } } #[test] diff --git a/src/fun/transform/apply_args.rs b/src/fun/transform/apply_args.rs index 23201a2e1..daae94cbd 100644 --- a/src/fun/transform/apply_args.rs +++ b/src/fun/transform/apply_args.rs @@ -23,9 +23,10 @@ impl Ctx<'_> { // Since we fatal error, no need to exit early let n_rules = main_def.rules.len(); if n_rules != 1 { - self.info.add_rule_error( + self.info.add_function_error( format!("Expected the entrypoint function to have only one rule, found {n_rules}."), entrypoint.clone(), + None, ); } @@ -35,9 +36,10 @@ impl Ctx<'_> { if let Pattern::Var(var) = pat { main_body = Term::lam(Pattern::Var(var.clone()), main_body); } else { - self.info.add_rule_error( + self.info.add_function_error( format!("Expected the entrypoint function to only have variable patterns, found '{pat}'."), entrypoint.clone(), + None, ); } } diff --git a/src/fun/transform/definition_pruning.rs b/src/fun/transform/definition_pruning.rs index 74d623c00..5985805b2 100644 --- a/src/fun/transform/definition_pruning.rs +++ b/src/fun/transform/definition_pruning.rs @@ -1,5 +1,5 @@ use crate::{ - diagnostics::{FileSpan, WarningType}, + diagnostics::WarningType, fun::{Book, Ctx, Name, Source, Term}, maybe_grow, }; @@ -78,11 +78,12 @@ impl Ctx<'_> { if prune_all { rm_def(self.book, &def); } else if !def.is_generated() && !matches!(src, Source::Generated) { - let span = match src { - Source::Local(span) => Some(FileSpan::new(span, None)), - _ => None, - }; - self.info.add_rule_warning("Definition is unused.", WarningType::UnusedDefinition, def, span); + self.info.add_function_warning( + "Definition is unused.", + WarningType::UnusedDefinition, + def, + Some(&src), + ); } } Used::Ctr => { diff --git a/src/fun/transform/desugar_bend.rs b/src/fun/transform/desugar_bend.rs index fd9d9c723..0e1565a10 100644 --- a/src/fun/transform/desugar_bend.rs +++ b/src/fun/transform/desugar_bend.rs @@ -16,7 +16,7 @@ impl Ctx<'_> { let mut fresh = 0; for rule in def.rules.iter_mut() { if let Err(err) = rule.body.desugar_bend(&def.name, &mut fresh, &mut new_defs, &def.source) { - self.info.add_rule_error(err, def.name.clone()); + self.info.add_function_error(err, def.name.clone(), Some(&def.source)); break; } } diff --git a/src/fun/transform/desugar_fold.rs b/src/fun/transform/desugar_fold.rs index 0ab970835..6749a677e 100644 --- a/src/fun/transform/desugar_fold.rs +++ b/src/fun/transform/desugar_fold.rs @@ -43,7 +43,7 @@ impl Ctx<'_> { &def.source, ); if let Err(e) = res { - self.info.add_rule_error(e, def.name.clone()); + self.info.add_function_error(e, def.name.clone(), Some(&def.source)); } } } diff --git a/src/fun/transform/desugar_match_defs.rs b/src/fun/transform/desugar_match_defs.rs index de6acdec3..99984bb80 100644 --- a/src/fun/transform/desugar_match_defs.rs +++ b/src/fun/transform/desugar_match_defs.rs @@ -23,10 +23,15 @@ impl Ctx<'_> { match err { DesugarMatchDefErr::AdtNotExhaustive { .. } | DesugarMatchDefErr::NumMissingDefault - | DesugarMatchDefErr::TypeMismatch { .. } => self.info.add_rule_error(err, def_name.clone()), - DesugarMatchDefErr::RepeatedBind { .. } => { - self.info.add_rule_warning(err, WarningType::RepeatedBind, def_name.clone(), None) + | DesugarMatchDefErr::TypeMismatch { .. } => { + self.info.add_function_error(err, def_name.clone(), Some(&def.source)) } + DesugarMatchDefErr::RepeatedBind { .. } => self.info.add_function_warning( + err, + WarningType::RepeatedBind, + def_name.clone(), + Some(&def.source), + ), } } } diff --git a/src/fun/transform/desugar_open.rs b/src/fun/transform/desugar_open.rs index 016f1f739..7256e8a4d 100644 --- a/src/fun/transform/desugar_open.rs +++ b/src/fun/transform/desugar_open.rs @@ -11,7 +11,7 @@ impl Ctx<'_> { for def in self.book.defs.values_mut() { for rule in def.rules.iter_mut() { if let Err(err) = rule.body.desugar_open(&self.book.adts) { - self.info.add_rule_error(err, def.name.clone()); + self.info.add_function_error(err, def.name.clone(), Some(&def.source)); } } } diff --git a/src/fun/transform/desugar_with_blocks.rs b/src/fun/transform/desugar_with_blocks.rs index 14df5781e..821835c3b 100644 --- a/src/fun/transform/desugar_with_blocks.rs +++ b/src/fun/transform/desugar_with_blocks.rs @@ -15,7 +15,7 @@ impl Ctx<'_> { for def in self.book.defs.values_mut() { for rule in def.rules.iter_mut() { if let Err(e) = rule.body.desugar_with_blocks(None, &def_names) { - self.info.add_rule_error(e, def.name.clone()); + self.info.add_function_error(e, def.name.clone(), Some(&def.source)); } } } diff --git a/src/fun/transform/fix_match_defs.rs b/src/fun/transform/fix_match_defs.rs index 299fef471..c4fe1e789 100644 --- a/src/fun/transform/fix_match_defs.rs +++ b/src/fun/transform/fix_match_defs.rs @@ -19,7 +19,7 @@ impl Ctx<'_> { } for err in errs { - self.info.add_rule_error(err, def.name.clone()); + self.info.add_function_error(err, def.name.clone(), Some(&def.source)); } } diff --git a/src/fun/transform/fix_match_terms.rs b/src/fun/transform/fix_match_terms.rs index 11adfd5fc..37c90824c 100644 --- a/src/fun/transform/fix_match_terms.rs +++ b/src/fun/transform/fix_match_terms.rs @@ -51,17 +51,26 @@ impl Ctx<'_> { for err in errs { match err { FixMatchErr::AdtMismatch { .. } | FixMatchErr::NonExhaustiveMatch { .. } => { - self.info.add_rule_error(err, def.name.clone()) - } - FixMatchErr::IrrefutableMatch { .. } => { - self.info.add_rule_warning(err, WarningType::IrrefutableMatch, def.name.clone(), None) - } - FixMatchErr::UnreachableMatchArms { .. } => { - self.info.add_rule_warning(err, WarningType::UnreachableMatch, def.name.clone(), None) - } - FixMatchErr::RedundantArm { .. } => { - self.info.add_rule_warning(err, WarningType::RedundantMatch, def.name.clone(), None) + self.info.add_function_error(err, def.name.clone(), Some(&def.source)) } + FixMatchErr::IrrefutableMatch { .. } => self.info.add_function_warning( + err, + WarningType::IrrefutableMatch, + def.name.clone(), + Some(&def.source), + ), + FixMatchErr::UnreachableMatchArms { .. } => self.info.add_function_warning( + err, + WarningType::UnreachableMatch, + def.name.clone(), + Some(&def.source), + ), + FixMatchErr::RedundantArm { .. } => self.info.add_function_warning( + err, + WarningType::RedundantMatch, + def.name.clone(), + Some(&def.source), + ), } } } diff --git a/src/hvm/check_net_size.rs b/src/hvm/check_net_size.rs index ff733be60..5fdc3a434 100644 --- a/src/hvm/check_net_size.rs +++ b/src/hvm/check_net_size.rs @@ -10,9 +10,10 @@ pub fn check_net_sizes(book: &Book, diagnostics: &mut Diagnostics) -> Result<(), for (name, net) in &book.defs { let nodes = count_nodes(net); if nodes > MAX_NET_SIZE { - diagnostics.add_rule_error( + diagnostics.add_function_error( format!("Definition is too large for hvm (size={nodes}, max size={MAX_NET_SIZE}). Please break it into smaller pieces."), Name::new(name), + None ); } } diff --git a/src/imp/to_fun.rs b/src/imp/to_fun.rs index 5ecd33ec5..ac3e3a9ba 100644 --- a/src/imp/to_fun.rs +++ b/src/imp/to_fun.rs @@ -1,11 +1,11 @@ use super::{AssignPattern, Definition, Expr, InPlaceOp, Stmt}; use crate::{ - diagnostics::{Diagnostics, FileSpan}, + diagnostics::Diagnostics, fun::{ self, builtins::{LCONS, LNIL}, parser::ParseBook, - Book, Name, Source, + Book, Name, }, }; @@ -30,14 +30,9 @@ impl ParseBook { impl Definition { pub fn to_fun(self) -> Result { - let span = match self.source { - Source::Local(span) => Some(FileSpan::new(span, None)), - _ => None, - }; - let body = self.body.into_fun().map_err(|e| { let mut diags = Diagnostics::default(); - diags.add_function_error(e.display_only_messages(), self.name.clone(), span.clone()); + diags.add_function_error(e.display_only_messages(), self.name.clone(), Some(&self.source)); diags })?; @@ -45,7 +40,11 @@ impl Definition { StmtToFun::Return(term) => term, StmtToFun::Assign(..) => { let mut diags = Diagnostics::default(); - diags.add_function_error("Function doesn't end with a return statement", self.name, span); + diags.add_function_error( + "Function doesn't end with a return statement", + self.name, + Some(&self.source), + ); return Err(diags); } }; diff --git a/tests/snapshots/compile_file__mismatched_ask_statements.bend.snap b/tests/snapshots/compile_file__mismatched_ask_statements.bend.snap index 6053c2c78..01eb4e41a 100644 --- a/tests/snapshots/compile_file__mismatched_ask_statements.bend.snap +++ b/tests/snapshots/compile_file__mismatched_ask_statements.bend.snap @@ -3,5 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/mismatched_ask_statements.bend --- Errors: -In function 'main': +In definition 'main': 'match' arms end with different assignments. From e42add10c83b957e27f5b3c6160346ceac10424e Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Wed, 14 Aug 2024 13:57:43 -0300 Subject: [PATCH 15/24] Update Cargo.toml to avoid semantic versioning for HVM Co-authored-by: Nicolas Abril --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 9ee239bc9..aa4bdce81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ cli = ["dep:clap"] TSPL = "0.0.13" clap = { version = "4.4.1", features = ["derive"], optional = true } highlight_error = "0.1.1" -hvm = "2.0.22" +hvm = "=2.0.22" indexmap = "2.2.3" interner = "0.2.1" itertools = "0.11.0" From c86daacec0c72b0d0e27ffe3a57b6058f384a46b Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Wed, 14 Aug 2024 14:14:44 -0300 Subject: [PATCH 16/24] Change "repeated field" message to avoid printing expected term --- src/fun/parser.rs | 13 ++++++++++++- src/imp/parser.rs | 4 ++-- .../parse_file__repeated_datatype_name.bend.snap | 3 +-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/fun/parser.rs b/src/fun/parser.rs index 0c7df3221..0f34277a9 100644 --- a/src/fun/parser.rs +++ b/src/fun/parser.rs @@ -255,7 +255,7 @@ impl<'a> TermParser<'a> { let fields = self.list_like(parse_field, "", ")", "", false, 0)?; if let Some(field) = fields.find_repeated_names().into_iter().next() { let msg = format!("Found a repeated field '{field}' in constructor {ctr_name}."); - return self.expected_and("field", &msg)?; + return self.expected_message(&msg)?; } Ok((ctr_name, fields)) } else { @@ -1200,6 +1200,17 @@ impl Indent { impl<'a> ParserCommons<'a> for TermParser<'a> {} pub trait ParserCommons<'a>: Parser<'a> { + /// Generates an error message that does not print expected terms. + fn expected_message(&mut self, msg: &str) -> ParseResult { + let ini_idx = *self.index(); + let end_idx = *self.index() + 1; + + let is_eof = self.is_eof(); + let detected = DisplayFn(|f| if is_eof { write!(f, " end of input") } else { Ok(()) }); + let msg = format!("\x1b[1m- information:\x1b[0m {}\n\x1b[1m- location:\x1b[0m{}", msg, detected); + self.with_ctx(Err(msg), ini_idx..end_idx) + } + fn labelled(&mut self, parser: impl Fn(&mut Self) -> ParseResult, label: &str) -> ParseResult { match parser(self) { Ok(val) => Ok(val), diff --git a/src/imp/parser.rs b/src/imp/parser.rs index a986062e0..16d7c30f6 100644 --- a/src/imp/parser.rs +++ b/src/imp/parser.rs @@ -1081,7 +1081,7 @@ impl<'a> PyParser<'a> { } if let Some(field) = fields.find_repeated_names().into_iter().next() { let msg = format!("Found a repeated field '{field}' in constructor {ctr_name}."); - return self.expected_and("field", &msg); + return self.expected_message(&msg); } Ok(Variant { name: ctr_name, fields }) } @@ -1103,7 +1103,7 @@ impl<'a> PyParser<'a> { }; if let Some(field) = fields.find_repeated_names().into_iter().next() { let msg = format!("Found a repeated field '{field}' in object {name}."); - return self.expected_and("field", &msg); + return self.expected_message(&msg); } if !self.is_eof() { self.consume_new_line()?; diff --git a/tests/snapshots/parse_file__repeated_datatype_name.bend.snap b/tests/snapshots/parse_file__repeated_datatype_name.bend.snap index 59e8aacd4..59acfd920 100644 --- a/tests/snapshots/parse_file__repeated_datatype_name.bend.snap +++ b/tests/snapshots/parse_file__repeated_datatype_name.bend.snap @@ -5,7 +5,6 @@ input_file: tests/golden_tests/parse_file/repeated_datatype_name.bend Errors: In tests/golden_tests/parse_file/repeated_datatype_name.bend : - information: Found a repeated field 'Expr' in constructor Expr/Plus. -- expected: field -- detected: +- location:  3 | | (Plus Expr Expr)  From 66ac5dc1612108d44d3a4cbcf582e2021017fe8f Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Wed, 14 Aug 2024 15:02:16 -0300 Subject: [PATCH 17/24] Change `Stmt::into_fun` back into returning strings as errors --- src/imp/to_fun.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/imp/to_fun.rs b/src/imp/to_fun.rs index ac3e3a9ba..d3b57e2ef 100644 --- a/src/imp/to_fun.rs +++ b/src/imp/to_fun.rs @@ -32,7 +32,7 @@ impl Definition { pub fn to_fun(self) -> Result { let body = self.body.into_fun().map_err(|e| { let mut diags = Diagnostics::default(); - diags.add_function_error(e.display_only_messages(), self.name.clone(), Some(&self.source)); + diags.add_function_error(e, self.name.clone(), Some(&self.source)); diags })?; @@ -82,7 +82,7 @@ enum StmtToFun { Assign(bool, fun::Pattern, fun::Term), } -fn take(t: Stmt) -> Result<(bool, Option, fun::Term), Diagnostics> { +fn take(t: Stmt) -> Result<(bool, Option, fun::Term), String> { match t.into_fun()? { StmtToFun::Return(ret) => Ok((false, None, ret)), StmtToFun::Assign(x, pat, val) => Ok((x, Some(pat), val)), @@ -98,7 +98,7 @@ fn wrap(nxt: Option, term: fun::Term, ask: bool) -> StmtToFun { } impl Stmt { - fn into_fun(self) -> Result { + fn into_fun(self) -> Result { // TODO: Refactor this to not repeat everything. // TODO: When we have an error with an assignment, we should show the offending assignment (eg. "{pat} = ..."). let stmt_to_fun = match self { @@ -355,7 +355,7 @@ impl Stmt { Stmt::Return { term } => StmtToFun::Return(term.to_fun()), Stmt::LocalDef { def, nxt } => { let (ask, nxt_pat, nxt) = take(*nxt)?; - let def = def.to_fun()?; + let def = def.to_fun().map_err(|e| e.display_only_messages().to_string())?; let term = fun::Term::Def { def, nxt: Box::new(nxt) }; wrap(nxt_pat, term, ask) } @@ -470,7 +470,7 @@ fn wrap_nxt_assign_stmt( nxt: Option>, pat: Option, ask: bool, -) -> Result { +) -> Result { if let Some(nxt) = nxt { if let Some(pat) = pat { let (ask_nxt, nxt_pat, nxt) = take(*nxt)?; From d67080b6310ea669da2f70cdbf16b8b84b105062 Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Thu, 15 Aug 2024 19:07:02 -0300 Subject: [PATCH 18/24] Refactor range reporting system to be a simple `Source` --- src/diagnostics.rs | 173 ++++++++++-------- src/fun/check/unbound_refs.rs | 2 +- src/fun/check/unbound_vars.rs | 2 +- src/fun/load_book.rs | 8 +- src/fun/mod.rs | 34 ++-- src/fun/net_to_term.rs | 7 +- src/fun/parser.rs | 63 +++++-- src/fun/transform/apply_args.rs | 4 +- src/fun/transform/definition_pruning.rs | 6 +- src/fun/transform/desugar_bend.rs | 2 +- src/fun/transform/desugar_fold.rs | 2 +- src/fun/transform/desugar_match_defs.rs | 4 +- src/fun/transform/desugar_open.rs | 2 +- src/fun/transform/desugar_with_blocks.rs | 2 +- src/fun/transform/fix_match_defs.rs | 2 +- src/fun/transform/fix_match_terms.rs | 8 +- src/hvm/check_net_size.rs | 2 +- src/imp/parser.rs | 5 +- src/imp/to_fun.rs | 4 +- src/imports/book.rs | 6 +- tests/snapshots/cli__desugar_merge.bend.snap | 1 + tests/snapshots/cli__desugar_pretty.bend.snap | 1 + .../cli__input_file_not_found.bend.snap | 1 + tests/snapshots/cli__warn_and_err.bend.snap | 2 + .../compile_file__360_no_scope.bend.snap | 2 +- .../compile_file__ask_outside_do.bend.snap | 1 + .../compile_file__cyclic_global_lam.bend.snap | 1 + .../compile_file__elif_no_else.bend.snap | 2 +- ...ompile_file__error_data_def_name.bend.snap | 2 +- .../compile_file__error_messages.bend.snap | 1 + .../compile_file__just_a_name.bend.snap | 2 +- .../compile_file__just_data.bend.snap | 2 +- .../compile_file__just_paren.bend.snap | 2 +- .../compile_file__just_rule_paren.bend.snap | 2 +- ..._file__mismatched_ask_statements.bend.snap | 1 + .../compile_file__missing_adt_eq.bend.snap | 2 +- .../compile_file__missing_ctrs.bend.snap | 2 +- .../compile_file__missing_pat.bend.snap | 2 +- ...ile_file__nested_ctr_wrong_arity.bend.snap | 1 + .../compile_file__number_too_large.bend.snap | 2 +- .../compile_file__ref_to_main.bend.snap | 1 + ...compile_file__repeated_bind_rule.bend.snap | 1 + ...ompile_file__switch_all_patterns.bend.snap | 2 +- .../compile_file__switch_incomplete.bend.snap | 2 +- ..._file__top_level_name_slashslash.bend.snap | 2 +- ...mpile_file__unbound_unscoped_var.bend.snap | 1 + .../compile_file__unbound_var.bend.snap | 1 + .../compile_file__unbound_var_scope.bend.snap | 1 + ...e_file__unbound_with_tup_pattern.bend.snap | 1 + ...ompile_file__unexpected_top_char.bend.snap | 2 +- .../compile_file__unscoped_dup_use.bend.snap | 1 + ...mpile_file__unused_unscoped_bind.bend.snap | 1 + ..._variable_name_double_underscore.bend.snap | 2 +- .../compile_file__vicious_circles.bend.snap | 1 + .../compile_file__warn_and_err.bend.snap | 2 + ...pile_file__with_clause_parse_err.bend.snap | 2 +- .../compile_file__wrong_ctr_arity.bend.snap | 1 + ...ompile_file__wrong_ctr_var_arity.bend.snap | 1 + .../compile_file__wrong_nums.bend.snap | 2 +- ...mpile_file__wrong_unicode_escape.bend.snap | 2 +- .../compile_file_o_all__adt_string.bend.snap | 2 +- ...ll__bad_parens_making_erased_let.bend.snap | 1 + .../compile_file_o_all__cyclic_dup.bend.snap | 1 + .../compile_file_o_all__double_main.bend.snap | 1 + ..._o_all__match_adt_non_exhaustive.bend.snap | 1 + ...e_file_o_all__non_exhaustive_and.bend.snap | 1 + ...__non_exhaustive_different_types.bend.snap | 1 + ...le_o_all__non_exhaustive_pattern.bend.snap | 1 + ..._file_o_all__non_exhaustive_tree.bend.snap | 1 + ...e_o_all__repeated_name_trucation.bend.snap | 1 + .../compile_file_o_all__self_ref.bend.snap | 2 + .../compile_file_o_all__tagged_dup.bend.snap | 2 +- .../compile_file_o_all__tagged_lam.bend.snap | 2 +- .../compile_file_o_all__tagged_sup.bend.snap | 2 +- ...pile_file_o_no_all__bitonic_sort.bend.snap | 1 + ...pile_file_o_no_all__list_reverse.bend.snap | 1 + .../compile_file_o_no_all__sum_tree.bend.snap | 1 + .../compile_long__huge_tree.bend.snap | 1 + .../compile_long__long_str_file.bend.snap | 1 + ...esugar_file__non_exaustive_limit.bend.snap | 1 + .../import_system__import_main.bend.snap | 1 + .../import_system__import_main2.bend.snap | 1 + .../import_system__import_main3.bend.snap | 1 + ...ort_system__imports_alias_shadow.bend.snap | 1 + .../import_system__imports_conflict.bend.snap | 1 + ...m__imports_file_and_dir_conflict.bend.snap | 1 + .../import_system__imports_shadow.bend.snap | 1 + .../import_system__imports_shadow2.bend.snap | 1 + .../mutual_recursion__a_b_c.bend.snap | 1 + .../mutual_recursion__merged.bend.snap | 1 + .../mutual_recursion__multiple.bend.snap | 1 + .../mutual_recursion__odd_even.bend.snap | 1 + .../parse_file__bad_floating.bend.snap | 2 +- .../parse_file__bend_missing_else.bend.snap | 2 +- .../parse_file__fold_missing_case.bend.snap | 2 +- .../parse_file__fun_def_name.bend.snap | 2 +- .../parse_file__if_missing_else.bend.snap | 2 +- .../parse_file__match_missing_case.bend.snap | 2 +- ...parse_file__redefinition_builtin.bend.snap | 2 +- ..._file__redefinition_ctr_with_fun.bend.snap | 2 +- ...parse_file__redefinition_fun_imp.bend.snap | 2 +- ...parse_file__redefinition_imp_fun.bend.snap | 2 +- ...e__redefinition_type_with_object.bend.snap | 2 +- ...e__redefinition_with_def_between.bend.snap | 2 +- ...redefinition_with_object_between.bend.snap | 2 +- ...__redefinition_with_type_between.bend.snap | 2 +- .../parse_file__repeated_adt_name.bend.snap | 2 +- ...rse_file__repeated_datatype_name.bend.snap | 2 +- .../parse_file__strange_pattern.bend.snap | 2 +- tests/snapshots/parse_file__tab.bend.snap | 2 +- .../parse_file__tuple_need_parens.bend.snap | 2 +- .../snapshots/readback_hvm__bad_net.bend.snap | 1 + .../readback_hvm__invalid_op2_op2.bend.snap | 1 + .../run_file__360_no_scope.bend.snap | 2 +- .../run_file__adt_match_wrong_tag.bend.snap | 2 +- .../run_file__adt_wrong_tag.bend.snap | 2 +- .../run_file__def_bool_num.bend.snap | 1 + .../run_file__def_num_bool.bend.snap | 1 + tests/snapshots/run_file__empty.bend.snap | 1 + tests/snapshots/run_file__exp.bend.snap | 2 + .../run_file__let_tup_readback.bend.snap | 2 + tests/snapshots/run_file__match_sup.bend.snap | 2 +- .../snapshots/run_file__match_vars.bend.snap | 1 + tests/snapshots/run_file__nat_add.bend.snap | 2 +- .../snapshots/run_file__nat_add_num.bend.snap | 2 +- .../run_file__num_match_missing_var.bend.snap | 2 +- .../run_file__open_too_many_ctrs.bend.snap | 1 + .../run_file__open_undefined_type.bend.snap | 1 + .../run_file__override_list_ctr.bend.snap | 2 +- .../run_file__override_str_ctr.bend.snap | 2 +- .../run_file__readback_hvm1_main.bend.snap | 1 + ...ile__recursive_combinator_nested.bend.snap | 2 +- tests/snapshots/run_file__str_inc.bend.snap | 2 +- .../snapshots/run_file__str_inc_eta.bend.snap | 2 +- .../snapshots/run_file__tagged_lam.bend.snap | 2 +- .../run_file__unbound_wrap.bend.snap | 1 + .../run_file__unscoped_never_used.bend.snap | 1 + ...simplify_matches__wrong_fn_arity.bend.snap | 3 + 138 files changed, 326 insertions(+), 192 deletions(-) diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 6607e557d..05b83287f 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use TSPL::ParseError; use crate::fun::{display::DisplayFn, Name, Source}; @@ -33,7 +34,7 @@ pub struct DiagnosticsConfig { pub struct Diagnostic { pub message: String, pub severity: Severity, - pub span: Option, + pub source: Source, } #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] @@ -74,30 +75,29 @@ impl Diagnostics { Self { err_counter: 0, diagnostics: Default::default(), config } } - pub fn add_parsing_error(&mut self, err: impl std::fmt::Display, span: FileSpan) { + pub fn add_parsing_error(&mut self, err: impl std::fmt::Display, source: Source) { self.err_counter += 1; - self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Parsing, Some(span)); + self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Parsing, source); } pub fn add_book_error(&mut self, err: impl std::fmt::Display) { self.err_counter += 1; - self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Book, None); + self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Book, Default::default()); } - pub fn add_function_error(&mut self, err: impl std::fmt::Display, name: Name, source: Option<&Source>) { + pub fn add_function_error(&mut self, err: impl std::fmt::Display, name: Name, source: Source) { self.err_counter += 1; - let span = source.and_then(|src| src.span()).map(|s| FileSpan::new(s, None)); self.add_diagnostic( err, Severity::Error, DiagnosticOrigin::Function(name.def_name_from_generated()), - span, + source, ); } pub fn add_inet_error(&mut self, err: impl std::fmt::Display, def_name: String) { self.err_counter += 1; - self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Inet(def_name), None); + self.add_diagnostic(err, Severity::Error, DiagnosticOrigin::Inet(def_name), Default::default()); } pub fn add_function_warning( @@ -105,14 +105,18 @@ impl Diagnostics { warn: impl std::fmt::Display, warn_type: WarningType, def_name: Name, - source: Option<&Source>, + source: Source, ) { let severity = self.config.warning_severity(warn_type); if severity == Severity::Error { self.err_counter += 1; } - let span = source.and_then(|src| src.span()).map(|s| FileSpan::new(s, None)); - self.add_diagnostic(warn, severity, DiagnosticOrigin::Function(def_name.def_name_from_generated()), span); + self.add_diagnostic( + warn, + severity, + DiagnosticOrigin::Function(def_name.def_name_from_generated()), + source, + ); } pub fn add_book_warning(&mut self, warn: impl std::fmt::Display, warn_type: WarningType) { @@ -120,7 +124,7 @@ impl Diagnostics { if severity == Severity::Error { self.err_counter += 1; } - self.add_diagnostic(warn, severity, DiagnosticOrigin::Book, None); + self.add_diagnostic(warn, severity, DiagnosticOrigin::Book, Default::default()); } pub fn add_diagnostic( @@ -128,9 +132,9 @@ impl Diagnostics { msg: impl std::fmt::Display, severity: Severity, orig: DiagnosticOrigin, - range: Option, + source: Source, ) { - let diag = Diagnostic { message: msg.to_string(), severity, span: range }; + let diag = Diagnostic { message: msg.to_string(), severity, source }; self.diagnostics.entry(orig).or_default().push(diag) } @@ -142,7 +146,7 @@ impl Diagnostics { match result { Ok(t) => Some(t), Err(e) => { - self.add_function_error(e, def_name, None); + self.add_function_error(e, def_name, Default::default()); None } } @@ -189,52 +193,90 @@ impl Diagnostics { /// Returns a Display that prints the diagnostics with one of the given severities. pub fn display_with_severity(&self, severity: Severity) -> impl std::fmt::Display + '_ { DisplayFn(move |f| { - fn filter<'a>( - errs: impl IntoIterator, - severity: Severity, - ) -> impl Iterator { - errs.into_iter().filter(move |err| err.severity == severity) - } - - let mut has_msg = false; - for (orig, errs) in &self.diagnostics { - let mut errs = filter(errs, severity).peekable(); - if errs.peek().is_some() { - match orig { - DiagnosticOrigin::Parsing => { - for err in errs { - writeln!(f, "{err}")?; + // We want to print diagnostics information somewhat like this: + // ``` + // In file A : + // In definition X : + // {error} + // In definition Y : + // {error} + // + // In file B : + // In compiled Inet Z : + // {error} + // {...} + // ``` + // The problem is, diagnostics data is currently structured as a mapping from something like + // DiagnosticOrigin to (DiagnosticMessage, DiagnosticFile), and we would need something + // like a mapping from DiagnosticFile to DiagnosticOrigin to DiagnosticMessage in order + // to print it cleanly. We might want to change it later to have this structure, + // but meanwhile, we do the transformations below to make the goal possible. + + // Flatten Iter<(Origin, Vec)> into Iter<(Origin, Diagnostic)> + let diagnostics = self + .diagnostics + .iter() + .flat_map(|(origin, diagnostics)| diagnostics.iter().map(move |diagnostic| (origin, diagnostic))); + // Remove diagnostics with unwanted Severity + let diagnostics = diagnostics.filter(|(_, diag)| diag.severity == severity); + // Group diagnostics by their file names + let file_groups = diagnostics.group_by(|diag| diag.1.source.file.as_ref()); + + // Now, we have a mapping from DiagnosticFile to (DiagnosticOrigin, DiagnosticMessage). + for (file, origins_and_diagnostics) in &file_groups { + // We don't have to check if the amount of diagnostics in this file is greater than 0, + // since we will only get a file if it was included in a diagnostic. + match &file { + Some(name) => writeln!(f, "\x1b[1mIn \x1b[4m{}\x1b[0m\x1b[1m :\x1b[0m", name)?, + None => writeln!(f, "\x1b[1mDuring execution :\x1b[0m")?, + }; + + // Group errors by their origin + let origin_groups = origins_and_diagnostics.group_by(|(origin, _)| *origin); + + let mut has_msg = false; + // Finally, we have our mapping of DiagnosticOrigin to DiagnosticMessage back. + for (origin, origins_and_diagnostics) in &origin_groups { + // We don't care about DiagnosticOrigins here, so remove them. + let mut diagnostics = origins_and_diagnostics.map(|(_, diag)| diag).peekable(); + + if diagnostics.peek().is_some() { + match origin { + DiagnosticOrigin::Parsing => { + for err in diagnostics { + writeln!(f, "{err}")?; + } } - } - DiagnosticOrigin::Book => { - for err in errs { - writeln!(f, "{err}")?; + DiagnosticOrigin::Book => { + for err in diagnostics { + writeln!(f, "{err}")?; + } } - } - DiagnosticOrigin::Function(nam) => { - writeln!(f, "\x1b[1mIn definition '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; - for err in errs { - writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; + DiagnosticOrigin::Function(nam) => { + writeln!(f, "\x1b[1mIn definition '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; + for err in diagnostics { + writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; + } } - } - DiagnosticOrigin::Inet(nam) => { - writeln!(f, "\x1b[1mIn compiled inet '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; - for err in errs { - writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; + DiagnosticOrigin::Inet(nam) => { + writeln!(f, "\x1b[1mIn compiled inet '\x1b[4m{}\x1b[0m\x1b[1m':\x1b[0m", nam)?; + for err in diagnostics { + writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; + } } - } - DiagnosticOrigin::Readback => { - writeln!(f, "\x1b[1mDuring readback:\x1b[0m")?; - for err in errs { - writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; + DiagnosticOrigin::Readback => { + writeln!(f, "\x1b[1mDuring readback:\x1b[0m")?; + for err in diagnostics { + writeln!(f, "{:ERR_INDENT_SIZE$}{err}", "")?; + } } } + has_msg = true; } - has_msg = true; } - } - if has_msg { - writeln!(f)?; + if has_msg { + writeln!(f)?; + } } Ok(()) }) @@ -267,7 +309,7 @@ impl From for Diagnostics { Self { diagnostics: BTreeMap::from_iter([( DiagnosticOrigin::Book, - vec![Diagnostic { message: value, severity: Severity::Error, span: None }], + vec![Diagnostic { message: value, severity: Severity::Error, source: Default::default() }], )]), ..Default::default() } @@ -284,7 +326,7 @@ impl From for Diagnostics { Self { diagnostics: BTreeMap::from_iter([( DiagnosticOrigin::Parsing, - vec![Diagnostic { message: value.into(), severity: Severity::Error, span: None }], + vec![Diagnostic { message: value.into(), severity: Severity::Error, source: Default::default() }], )]), ..Default::default() } @@ -331,12 +373,7 @@ impl Default for DiagnosticsConfig { impl Display for Diagnostic { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - // TODO: this could be problematic when printing multiple errors from the same file - // currently, there shouldn't be any `Diagnostics` with multiple problems `FileSpan`s - match &self.span { - Some(FileSpan { file: Some(file), .. }) => write!(f, "In {} :\n{}", file, self.message), - _ => write!(f, "{}", self.message), - } + write!(f, "{}", self.message) } } @@ -443,17 +480,3 @@ impl TextSpan { TextSpan::new(TextLocation::new(start_line, start_char), TextLocation::new(end_line, end_char)) } } - -#[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Ord, Eq)] -pub struct FileSpan { - pub span: TextSpan, - // Storing files as Strings, could be done as file IDs in the future - // This is currently optional, we might want to change it later - pub file: Option, -} - -impl FileSpan { - pub fn new(span: TextSpan, origin: Option<&str>) -> Self { - FileSpan { span, file: origin.map(|s| s.into()) } - } -} diff --git a/src/fun/check/unbound_refs.rs b/src/fun/check/unbound_refs.rs index 7a7f11ab8..1aa4cd5e5 100644 --- a/src/fun/check/unbound_refs.rs +++ b/src/fun/check/unbound_refs.rs @@ -17,7 +17,7 @@ impl Ctx<'_> { self.info.add_function_error( format!("Reference to undefined function '{unbound}'"), def.name.clone(), - Some(&def.source), + def.source.clone(), ); } } diff --git a/src/fun/check/unbound_vars.rs b/src/fun/check/unbound_vars.rs index b6fe34a40..61b6a36e1 100644 --- a/src/fun/check/unbound_vars.rs +++ b/src/fun/check/unbound_vars.rs @@ -28,7 +28,7 @@ impl Ctx<'_> { } for err in errs { - self.info.add_function_error(err, def_name.clone(), Some(&def.source)); + self.info.add_function_error(err, def_name.clone(), def.source.clone()); } } diff --git a/src/fun/load_book.rs b/src/fun/load_book.rs index 41018a17a..a88c45097 100644 --- a/src/fun/load_book.rs +++ b/src/fun/load_book.rs @@ -1,9 +1,9 @@ use super::{ parser::{ParseBook, TermParser}, - Book, Name, + Book, Name, Source, SourceKind, }; use crate::{ - diagnostics::{Diagnostics, DiagnosticsConfig, FileSpan, TextSpan}, + diagnostics::{Diagnostics, DiagnosticsConfig, TextSpan}, imports::PackageLoader, }; use std::path::Path; @@ -44,7 +44,9 @@ pub fn do_parse_book(code: &str, origin: &Path, mut book: ParseBook) -> Result

, + pub span: Option, + pub kind: SourceKind, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum SourceKind { + /// Built into the language. Builtin, /// Was generated by the compiler. Generated, - /// Source code location from the current book. - Local(TextSpan), - /// Imported from another package. + /// Source code from a local book. + User, + /// Source code from an imported book. Imported, + /// Unknown by the compiler at this stage. + Unknown, } /// An HVM native definition. @@ -1022,7 +1032,8 @@ impl Definition { } pub fn new_gen(name: Name, rules: Vec, builtin: bool) -> Self { - let source = if builtin { Source::Builtin } else { Source::Generated }; + let kind = if builtin { SourceKind::Builtin } else { SourceKind::Generated }; + let source = Source { file: None, span: None, kind }; Self { name, rules, source } } @@ -1117,18 +1128,17 @@ impl Book { impl Source { pub fn is_builtin(&self) -> bool { - matches!(self, Source::Builtin) + matches!(self.kind, SourceKind::Builtin) } pub fn is_local(&self) -> bool { - matches!(self, Source::Local(..)) + matches!(self.kind, SourceKind::User) } +} - pub fn span(&self) -> Option { - match self { - Source::Local(span) => Some(*span), - _ => None, - } +impl Default for Source { + fn default() -> Self { + Self { file: None, span: None, kind: SourceKind::Unknown } } } diff --git a/src/fun/net_to_term.rs b/src/fun/net_to_term.rs index 27a2d252a..764b4d333 100644 --- a/src/fun/net_to_term.rs +++ b/src/fun/net_to_term.rs @@ -550,7 +550,12 @@ impl Reader<'_> { for (err, count) in err_counts { let count_msg = if count > 1 { format!(" ({count} occurrences)") } else { "".to_string() }; let msg = format!("{}{}", err, count_msg); - diagnostics.add_diagnostic(msg.as_str(), Severity::Warning, DiagnosticOrigin::Readback, None); + diagnostics.add_diagnostic( + msg.as_str(), + Severity::Warning, + DiagnosticOrigin::Readback, + Default::default(), + ); } } diff --git a/src/fun/parser.rs b/src/fun/parser.rs index 0f34277a9..3bb8f1709 100644 --- a/src/fun/parser.rs +++ b/src/fun/parser.rs @@ -15,6 +15,8 @@ use indexmap::IndexMap; use itertools::Itertools; use TSPL::{ParseError, Parser}; +use super::SourceKind; + type FunDefinition = super::Definition; type ImpDefinition = crate::imp::Definition; @@ -165,8 +167,12 @@ impl<'a> TermParser<'a> { self.index = rewind_index; let (nam, ctrs) = self.parse_datatype()?; let end_idx = *self.index(); - let span = TextSpan::from_byte_span(self.input(), ini_idx..end_idx); - let source = if builtin { Source::Builtin } else { Source::Local(span) }; + + let span = Some(TextSpan::from_byte_span(self.input(), ini_idx..end_idx)); + let kind = if builtin { SourceKind::Builtin } else { SourceKind::User }; + let file = Some(book.source.to_string()); + let source = Source { file, span, kind }; + let adt = Adt { ctrs, source }; self.add_fun_type(&mut book, nam, adt, ini_idx..end_idx)?; indent = self.advance_newlines()?; @@ -278,8 +284,12 @@ impl<'a> TermParser<'a> { let body = p.parse_net()?; *self.index() = ini_idx + *p.index(); let end_idx = *self.index(); - let span = TextSpan::from_byte_span(self.input(), ini_idx..end_idx); - let source = if builtin { Source::Builtin } else { Source::Local(span) }; + + let span = Some(TextSpan::from_byte_span(self.input(), ini_idx..end_idx)); + let kind = if builtin { SourceKind::Builtin } else { SourceKind::User }; + let file = None; // should we pass the book's source here? + let source = Source { file, span, kind }; + let def = HvmDefinition { name: name.clone(), body, source }; Ok(def) } @@ -653,8 +663,9 @@ impl<'a> TermParser<'a> { if name == "def" { // parse the nxt def term. self.index = nxt_def; - let span = TextSpan::from_byte_span(self.input(), nxt_def..*self.index()); - let def = FunDefinition::new(name, rules, Source::Local(span)); + let span = Some(TextSpan::from_byte_span(self.input(), nxt_def..*self.index())); + let source = Source { span, file: None, kind: SourceKind::User }; + let def = FunDefinition::new(name, rules, source); return Ok(Term::Def { def, nxt: Box::new(self.parse_term()?) }); } if name == cur_name { @@ -672,8 +683,8 @@ impl<'a> TermParser<'a> { } } let nxt = self.parse_term()?; - let span = TextSpan::from_byte_span(self.input(), nxt_term..*self.index()); - let def = FunDefinition::new(cur_name, rules, Source::Local(span)); + let span = Some(TextSpan::from_byte_span(self.input(), nxt_term..*self.index())); + let def = FunDefinition::new(cur_name, rules, Source { span, file: None, kind: SourceKind::User }); return Ok(Term::Def { def, nxt: Box::new(nxt) }); } @@ -938,7 +949,7 @@ impl<'a> TermParser<'a> { // Continuing with a new rule to the current definition (Some(def), Some(last_rule)) if last_rule == name => { def.rules.push(rule); - if let Source::Local(s) = &mut def.source { + if let Some(s) = &mut def.source.span { s.end = TextLocation::from_byte_loc(self.input(), span.end); } } @@ -955,8 +966,10 @@ impl<'a> TermParser<'a> { // Adding the first rule of a new definition (None, _) => { self.check_top_level_redefinition(name, book, span.clone())?; - let span = TextSpan::from_byte_span(self.input(), span.start..span.end); - let source = if builtin { Source::Builtin } else { Source::Local(span) }; + let span = Some(TextSpan::from_byte_span(self.input(), span.start..span.end)); + let file = Some(book.source.to_string()); + let kind = if builtin { SourceKind::Builtin } else { SourceKind::User }; + let source = Source { file, span, kind }; book.fun_defs.insert(name.clone(), FunDefinition::new(name.clone(), vec![rule], source)); } } @@ -971,8 +984,10 @@ impl<'a> TermParser<'a> { builtin: bool, ) -> ParseResult<()> { self.check_top_level_redefinition(&def.name, book, span.clone())?; - let span = TextSpan::from_byte_span(self.input(), span.start..span.end); - let source = if builtin { Source::Builtin } else { Source::Local(span) }; + let span = Some(TextSpan::from_byte_span(self.input(), span.start..span.end)); + let kind = if builtin { SourceKind::Builtin } else { SourceKind::User }; + let file = Some(book.source.to_string()); + let source = Source { file, span, kind }; def.source = source; book.imp_defs.insert(def.name.clone(), def); Ok(()) @@ -988,15 +1003,19 @@ impl<'a> TermParser<'a> { &mut self, enum_: Enum, book: &mut ParseBook, - span: Range, + range: Range, builtin: bool, ) -> ParseResult<()> { - self.check_type_redefinition(&enum_.name, book, span.clone())?; - let text_span = TextSpan::from_byte_span(self.input(), span.start..span.end); - let source = if builtin { Source::Builtin } else { Source::Local(text_span) }; + self.check_type_redefinition(&enum_.name, book, range.clone())?; + + let span = Some(TextSpan::from_byte_span(self.input(), range.start..range.end)); + let kind = if builtin { SourceKind::Builtin } else { SourceKind::User }; + let file = Some(book.source.to_string()); + let source = Source { file, span, kind }; + let mut adt = Adt { ctrs: Default::default(), source }; for variant in enum_.variants { - self.check_top_level_redefinition(&enum_.name, book, span.clone())?; + self.check_top_level_redefinition(&enum_.name, book, range.clone())?; book.ctrs.insert(variant.name.clone(), enum_.name.clone()); adt.ctrs.insert(variant.name, variant.fields); } @@ -1042,8 +1061,12 @@ impl<'a> TermParser<'a> { ) -> ParseResult<()> { self.check_type_redefinition(&obj.name, book, span.clone())?; self.check_top_level_redefinition(&obj.name, book, span.clone())?; - let span = TextSpan::from_byte_span(self.input(), span.start..span.end); - let source = if builtin { Source::Builtin } else { Source::Local(span) }; + + let span = Some(TextSpan::from_byte_span(self.input(), span.start..span.end)); + let kind = if builtin { SourceKind::Builtin } else { SourceKind::User }; + let file = Some(book.source.to_string()); + let source = Source { file, span, kind }; + let mut adt = Adt { ctrs: Default::default(), source }; book.ctrs.insert(obj.name.clone(), obj.name.clone()); adt.ctrs.insert(obj.name.clone(), obj.fields); diff --git a/src/fun/transform/apply_args.rs b/src/fun/transform/apply_args.rs index daae94cbd..f1bf8b9a3 100644 --- a/src/fun/transform/apply_args.rs +++ b/src/fun/transform/apply_args.rs @@ -26,7 +26,7 @@ impl Ctx<'_> { self.info.add_function_error( format!("Expected the entrypoint function to have only one rule, found {n_rules}."), entrypoint.clone(), - None, + main_def.source.clone(), ); } @@ -39,7 +39,7 @@ impl Ctx<'_> { self.info.add_function_error( format!("Expected the entrypoint function to only have variable patterns, found '{pat}'."), entrypoint.clone(), - None, + main_def.source.clone(), ); } } diff --git a/src/fun/transform/definition_pruning.rs b/src/fun/transform/definition_pruning.rs index 5985805b2..8f7b9b586 100644 --- a/src/fun/transform/definition_pruning.rs +++ b/src/fun/transform/definition_pruning.rs @@ -1,6 +1,6 @@ use crate::{ diagnostics::WarningType, - fun::{Book, Ctx, Name, Source, Term}, + fun::{Book, Ctx, Name, SourceKind, Term}, maybe_grow, }; use hvm::ast::{Net, Tree}; @@ -77,12 +77,12 @@ impl Ctx<'_> { // Prune if `prune_all`, otherwise show a warning. if prune_all { rm_def(self.book, &def); - } else if !def.is_generated() && !matches!(src, Source::Generated) { + } else if !def.is_generated() && !matches!(src.kind, SourceKind::Generated) { self.info.add_function_warning( "Definition is unused.", WarningType::UnusedDefinition, def, - Some(&src), + src, ); } } diff --git a/src/fun/transform/desugar_bend.rs b/src/fun/transform/desugar_bend.rs index 0e1565a10..3d0753c1f 100644 --- a/src/fun/transform/desugar_bend.rs +++ b/src/fun/transform/desugar_bend.rs @@ -16,7 +16,7 @@ impl Ctx<'_> { let mut fresh = 0; for rule in def.rules.iter_mut() { if let Err(err) = rule.body.desugar_bend(&def.name, &mut fresh, &mut new_defs, &def.source) { - self.info.add_function_error(err, def.name.clone(), Some(&def.source)); + self.info.add_function_error(err, def.name.clone(), def.source.clone()); break; } } diff --git a/src/fun/transform/desugar_fold.rs b/src/fun/transform/desugar_fold.rs index 6749a677e..492cc9ed1 100644 --- a/src/fun/transform/desugar_fold.rs +++ b/src/fun/transform/desugar_fold.rs @@ -43,7 +43,7 @@ impl Ctx<'_> { &def.source, ); if let Err(e) = res { - self.info.add_function_error(e, def.name.clone(), Some(&def.source)); + self.info.add_function_error(e, def.name.clone(), def.source.clone()); } } } diff --git a/src/fun/transform/desugar_match_defs.rs b/src/fun/transform/desugar_match_defs.rs index 99984bb80..da7939d0b 100644 --- a/src/fun/transform/desugar_match_defs.rs +++ b/src/fun/transform/desugar_match_defs.rs @@ -24,13 +24,13 @@ impl Ctx<'_> { DesugarMatchDefErr::AdtNotExhaustive { .. } | DesugarMatchDefErr::NumMissingDefault | DesugarMatchDefErr::TypeMismatch { .. } => { - self.info.add_function_error(err, def_name.clone(), Some(&def.source)) + self.info.add_function_error(err, def_name.clone(), def.source.clone()) } DesugarMatchDefErr::RepeatedBind { .. } => self.info.add_function_warning( err, WarningType::RepeatedBind, def_name.clone(), - Some(&def.source), + def.source.clone(), ), } } diff --git a/src/fun/transform/desugar_open.rs b/src/fun/transform/desugar_open.rs index 7256e8a4d..0c662f162 100644 --- a/src/fun/transform/desugar_open.rs +++ b/src/fun/transform/desugar_open.rs @@ -11,7 +11,7 @@ impl Ctx<'_> { for def in self.book.defs.values_mut() { for rule in def.rules.iter_mut() { if let Err(err) = rule.body.desugar_open(&self.book.adts) { - self.info.add_function_error(err, def.name.clone(), Some(&def.source)); + self.info.add_function_error(err, def.name.clone(), def.source.clone()); } } } diff --git a/src/fun/transform/desugar_with_blocks.rs b/src/fun/transform/desugar_with_blocks.rs index 821835c3b..e163781f5 100644 --- a/src/fun/transform/desugar_with_blocks.rs +++ b/src/fun/transform/desugar_with_blocks.rs @@ -15,7 +15,7 @@ impl Ctx<'_> { for def in self.book.defs.values_mut() { for rule in def.rules.iter_mut() { if let Err(e) = rule.body.desugar_with_blocks(None, &def_names) { - self.info.add_function_error(e, def.name.clone(), Some(&def.source)); + self.info.add_function_error(e, def.name.clone(), def.source.clone()); } } } diff --git a/src/fun/transform/fix_match_defs.rs b/src/fun/transform/fix_match_defs.rs index c4fe1e789..c7a6e1b1f 100644 --- a/src/fun/transform/fix_match_defs.rs +++ b/src/fun/transform/fix_match_defs.rs @@ -19,7 +19,7 @@ impl Ctx<'_> { } for err in errs { - self.info.add_function_error(err, def.name.clone(), Some(&def.source)); + self.info.add_function_error(err, def.name.clone(), def.source.clone()); } } diff --git a/src/fun/transform/fix_match_terms.rs b/src/fun/transform/fix_match_terms.rs index 37c90824c..754cc88f8 100644 --- a/src/fun/transform/fix_match_terms.rs +++ b/src/fun/transform/fix_match_terms.rs @@ -51,25 +51,25 @@ impl Ctx<'_> { for err in errs { match err { FixMatchErr::AdtMismatch { .. } | FixMatchErr::NonExhaustiveMatch { .. } => { - self.info.add_function_error(err, def.name.clone(), Some(&def.source)) + self.info.add_function_error(err, def.name.clone(), def.source.clone()) } FixMatchErr::IrrefutableMatch { .. } => self.info.add_function_warning( err, WarningType::IrrefutableMatch, def.name.clone(), - Some(&def.source), + def.source.clone(), ), FixMatchErr::UnreachableMatchArms { .. } => self.info.add_function_warning( err, WarningType::UnreachableMatch, def.name.clone(), - Some(&def.source), + def.source.clone(), ), FixMatchErr::RedundantArm { .. } => self.info.add_function_warning( err, WarningType::RedundantMatch, def.name.clone(), - Some(&def.source), + def.source.clone(), ), } } diff --git a/src/hvm/check_net_size.rs b/src/hvm/check_net_size.rs index 4ed34c069..82a2abedf 100644 --- a/src/hvm/check_net_size.rs +++ b/src/hvm/check_net_size.rs @@ -23,7 +23,7 @@ pub fn check_net_sizes( diagnostics.add_function_error( format!("Definition is too large for HVM {target_lang} (size={nodes}, max size={net_size_bound}). Please break it into smaller pieces."), Name::new(name), - None + Default::default() ); } } diff --git a/src/imp/parser.rs b/src/imp/parser.rs index 16d7c30f6..dde651ba5 100644 --- a/src/imp/parser.rs +++ b/src/imp/parser.rs @@ -1,7 +1,7 @@ use crate::{ fun::{ parser::{is_num_char, Indent, ParseResult, ParserCommons}, - CtrField, Name, Num, Op, STRINGS, + CtrField, Name, Num, Op, Source, SourceKind, STRINGS, }, imp::{AssignPattern, Definition, Enum, Expr, InPlaceOp, MatchArm, Stmt, Variant}, maybe_grow, @@ -1037,7 +1037,8 @@ impl<'a> PyParser<'a> { indent.exit_level(); // Temporary source, should be overwritten later - let def = Definition { name, params, body, source: crate::fun::Source::Generated }; + let source = Source { file: None, span: None, kind: SourceKind::Generated }; + let def = Definition { name, params, body, source }; Ok((def, nxt_indent)) } diff --git a/src/imp/to_fun.rs b/src/imp/to_fun.rs index d3b57e2ef..114427e79 100644 --- a/src/imp/to_fun.rs +++ b/src/imp/to_fun.rs @@ -32,7 +32,7 @@ impl Definition { pub fn to_fun(self) -> Result { let body = self.body.into_fun().map_err(|e| { let mut diags = Diagnostics::default(); - diags.add_function_error(e, self.name.clone(), Some(&self.source)); + diags.add_function_error(e, self.name.clone(), self.source.clone()); diags })?; @@ -43,7 +43,7 @@ impl Definition { diags.add_function_error( "Function doesn't end with a return statement", self.name, - Some(&self.source), + self.source.clone(), ); return Err(diags); } diff --git a/src/imports/book.rs b/src/imports/book.rs index 10ad64c8e..e5ca981c5 100644 --- a/src/imports/book.rs +++ b/src/imports/book.rs @@ -1,7 +1,7 @@ use super::{BindMap, ImportsMap, PackageLoader}; use crate::{ diagnostics::{Diagnostics, DiagnosticsConfig}, - fun::{parser::ParseBook, Adt, Book, Definition, HvmDefinition, Name, Rule, Source, Term}, + fun::{parser::ParseBook, Adt, Book, Definition, HvmDefinition, Name, Rule, Source, SourceKind, Term}, imp::{self, Expr, Stmt}, imports::packages::Packages, }; @@ -166,7 +166,7 @@ impl ParseBook { // starting with `__` if not imported by the main book. for (mut name, mut adt) in adts { if adt.source.is_local() { - adt.source = Source::Imported; + adt.source.kind = SourceKind::Imported; name = Name::new(format!("{}/{}", src, name)); let mangle_name = !main_imports.contains_source(&name); @@ -217,7 +217,7 @@ impl ParseBook { // Applies the binds for the new names for every definition for (_, def) in self.local_defs_mut() { def.apply_binds(false, &canonical_map); - *def.source_mut() = Source::Imported; + def.source_mut().kind = SourceKind::Imported; } } } diff --git a/tests/snapshots/cli__desugar_merge.bend.snap b/tests/snapshots/cli__desugar_merge.bend.snap index 15fe92082..3df1b698b 100644 --- a/tests/snapshots/cli__desugar_merge.bend.snap +++ b/tests/snapshots/cli__desugar_merge.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/cli/desugar_merge.bend --- Warnings: +In tests/golden_tests/cli/desugar_merge.bend : In definition 'Z': Definition is unused. diff --git a/tests/snapshots/cli__desugar_pretty.bend.snap b/tests/snapshots/cli__desugar_pretty.bend.snap index bd6dca093..bd4e91c29 100644 --- a/tests/snapshots/cli__desugar_pretty.bend.snap +++ b/tests/snapshots/cli__desugar_pretty.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/cli/desugar_pretty.bend --- Warnings: +In tests/golden_tests/cli/desugar_pretty.bend : In definition 'Foo': Definition is unused. diff --git a/tests/snapshots/cli__input_file_not_found.bend.snap b/tests/snapshots/cli__input_file_not_found.bend.snap index 58ec93951..1575a9b27 100644 --- a/tests/snapshots/cli__input_file_not_found.bend.snap +++ b/tests/snapshots/cli__input_file_not_found.bend.snap @@ -3,4 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/cli/input_file_not_found.bend --- Errors: +During execution : The file 'tests/golden_tests/missing_dir/input_file_not_found.bend' was not found. diff --git a/tests/snapshots/cli__warn_and_err.bend.snap b/tests/snapshots/cli__warn_and_err.bend.snap index e972dc58c..33ca82179 100644 --- a/tests/snapshots/cli__warn_and_err.bend.snap +++ b/tests/snapshots/cli__warn_and_err.bend.snap @@ -3,9 +3,11 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/cli/warn_and_err.bend --- Warnings: +In tests/golden_tests/cli/warn_and_err.bend : In definition 'Foo': Repeated bind in pattern matching rule: 'a'. Errors: +In tests/golden_tests/cli/warn_and_err.bend : In definition 'Main': Unbound variable 'a'. diff --git a/tests/snapshots/compile_file__360_no_scope.bend.snap b/tests/snapshots/compile_file__360_no_scope.bend.snap index 905f60e6e..6037e7207 100644 --- a/tests/snapshots/compile_file__360_no_scope.bend.snap +++ b/tests/snapshots/compile_file__360_no_scope.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/360_no_scope.bend --- Errors: -In tests/golden_tests/compile_file/360_no_scope.bend : +In tests/golden_tests/compile_file/360_no_scope.bend : - expected: '=' - detected: end of input  6 |   diff --git a/tests/snapshots/compile_file__ask_outside_do.bend.snap b/tests/snapshots/compile_file__ask_outside_do.bend.snap index d8c0ab4b8..34f00a67d 100644 --- a/tests/snapshots/compile_file__ask_outside_do.bend.snap +++ b/tests/snapshots/compile_file__ask_outside_do.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/ask_outside_do.bend --- Errors: +In tests/golden_tests/compile_file/ask_outside_do.bend : In definition 'main': Monadic bind operation 'x <- ...' used outside of a `do` block. diff --git a/tests/snapshots/compile_file__cyclic_global_lam.bend.snap b/tests/snapshots/compile_file__cyclic_global_lam.bend.snap index 7514d226f..2d5a1ed6c 100644 --- a/tests/snapshots/compile_file__cyclic_global_lam.bend.snap +++ b/tests/snapshots/compile_file__cyclic_global_lam.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/cyclic_global_lam.bend --- Errors: +During execution : In compiled inet 'main': Found term that compiles into an inet with a vicious cycle diff --git a/tests/snapshots/compile_file__elif_no_else.bend.snap b/tests/snapshots/compile_file__elif_no_else.bend.snap index b812d1cb3..2db861c9c 100644 --- a/tests/snapshots/compile_file__elif_no_else.bend.snap +++ b/tests/snapshots/compile_file__elif_no_else.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/elif_no_else.bend --- Errors: -In tests/golden_tests/compile_file/elif_no_else.bend : +In tests/golden_tests/compile_file/elif_no_else.bend : - expected: 'else' or 'elif' - detected: end of input  6 |   diff --git a/tests/snapshots/compile_file__error_data_def_name.bend.snap b/tests/snapshots/compile_file__error_data_def_name.bend.snap index c9baf72df..cd3ddfcf8 100644 --- a/tests/snapshots/compile_file__error_data_def_name.bend.snap +++ b/tests/snapshots/compile_file__error_data_def_name.bend.snap @@ -3,6 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/error_data_def_name.bend --- Errors: -In tests/golden_tests/compile_file/error_data_def_name.bend : +In tests/golden_tests/compile_file/error_data_def_name.bend : Redefinition of constructor 'A/A'.  2 | A/A = 0 diff --git a/tests/snapshots/compile_file__error_messages.bend.snap b/tests/snapshots/compile_file__error_messages.bend.snap index 272abe75a..ec228477f 100644 --- a/tests/snapshots/compile_file__error_messages.bend.snap +++ b/tests/snapshots/compile_file__error_messages.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/error_messages.bend --- Errors: +In tests/golden_tests/compile_file/error_messages.bend : In definition 'Foo': Unbound constructor 'C' in pattern matching rule. Unbound constructor 'D' in pattern matching rule. diff --git a/tests/snapshots/compile_file__just_a_name.bend.snap b/tests/snapshots/compile_file__just_a_name.bend.snap index 363618199..83bbedf79 100644 --- a/tests/snapshots/compile_file__just_a_name.bend.snap +++ b/tests/snapshots/compile_file__just_a_name.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/just_a_name.bend --- Errors: -In tests/golden_tests/compile_file/just_a_name.bend : +In tests/golden_tests/compile_file/just_a_name.bend : - expected: pattern or '=' - detected: end of input  1 | asdf diff --git a/tests/snapshots/compile_file__just_data.bend.snap b/tests/snapshots/compile_file__just_data.bend.snap index 60d5214bf..e8c8a198d 100644 --- a/tests/snapshots/compile_file__just_data.bend.snap +++ b/tests/snapshots/compile_file__just_data.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/just_data.bend --- Errors: -In tests/golden_tests/compile_file/just_data.bend : +In tests/golden_tests/compile_file/just_data.bend : - expected: datatype name - detected: end of input  1 | type  diff --git a/tests/snapshots/compile_file__just_paren.bend.snap b/tests/snapshots/compile_file__just_paren.bend.snap index ed73d4b5a..473cdde5a 100644 --- a/tests/snapshots/compile_file__just_paren.bend.snap +++ b/tests/snapshots/compile_file__just_paren.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/just_paren.bend --- Errors: -In tests/golden_tests/compile_file/just_paren.bend : +In tests/golden_tests/compile_file/just_paren.bend : - expected: function name - detected: end of input  2 | (  diff --git a/tests/snapshots/compile_file__just_rule_paren.bend.snap b/tests/snapshots/compile_file__just_rule_paren.bend.snap index 9a98bcb38..65efb13d9 100644 --- a/tests/snapshots/compile_file__just_rule_paren.bend.snap +++ b/tests/snapshots/compile_file__just_rule_paren.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/just_rule_paren.bend --- Errors: -In tests/golden_tests/compile_file/just_rule_paren.bend : +In tests/golden_tests/compile_file/just_rule_paren.bend : - expected: '=' - detected: end of input  1 | (rule)  diff --git a/tests/snapshots/compile_file__mismatched_ask_statements.bend.snap b/tests/snapshots/compile_file__mismatched_ask_statements.bend.snap index 01eb4e41a..af79fef61 100644 --- a/tests/snapshots/compile_file__mismatched_ask_statements.bend.snap +++ b/tests/snapshots/compile_file__mismatched_ask_statements.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/mismatched_ask_statements.bend --- Errors: +In tests/golden_tests/compile_file/mismatched_ask_statements.bend : In definition 'main': 'match' arms end with different assignments. diff --git a/tests/snapshots/compile_file__missing_adt_eq.bend.snap b/tests/snapshots/compile_file__missing_adt_eq.bend.snap index 031163813..d73423579 100644 --- a/tests/snapshots/compile_file__missing_adt_eq.bend.snap +++ b/tests/snapshots/compile_file__missing_adt_eq.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/missing_adt_eq.bend --- Errors: -In tests/golden_tests/compile_file/missing_adt_eq.bend : +In tests/golden_tests/compile_file/missing_adt_eq.bend : - expected: '=' - detected: end of input  1 | type Adt  diff --git a/tests/snapshots/compile_file__missing_ctrs.bend.snap b/tests/snapshots/compile_file__missing_ctrs.bend.snap index 3c58706dd..820876baa 100644 --- a/tests/snapshots/compile_file__missing_ctrs.bend.snap +++ b/tests/snapshots/compile_file__missing_ctrs.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/missing_ctrs.bend --- Errors: -In tests/golden_tests/compile_file/missing_ctrs.bend : +In tests/golden_tests/compile_file/missing_ctrs.bend : - expected: datatype constructor name - detected: end of input  1 | type Adt =  diff --git a/tests/snapshots/compile_file__missing_pat.bend.snap b/tests/snapshots/compile_file__missing_pat.bend.snap index b5ab00d92..1d83f97e2 100644 --- a/tests/snapshots/compile_file__missing_pat.bend.snap +++ b/tests/snapshots/compile_file__missing_pat.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/missing_pat.bend --- Errors: -In tests/golden_tests/compile_file/missing_pat.bend : +In tests/golden_tests/compile_file/missing_pat.bend : - expected: name or '*' - detected:  2 | : * diff --git a/tests/snapshots/compile_file__nested_ctr_wrong_arity.bend.snap b/tests/snapshots/compile_file__nested_ctr_wrong_arity.bend.snap index 3a150fb56..1727dfc9f 100644 --- a/tests/snapshots/compile_file__nested_ctr_wrong_arity.bend.snap +++ b/tests/snapshots/compile_file__nested_ctr_wrong_arity.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/nested_ctr_wrong_arity.bend --- Errors: +In tests/golden_tests/compile_file/nested_ctr_wrong_arity.bend : In definition 'fst_fst': Incorrect arity for constructor 'Pair/Pair' of type 'Pair' in pattern matching rule. Expected 2 fields, found 1 diff --git a/tests/snapshots/compile_file__number_too_large.bend.snap b/tests/snapshots/compile_file__number_too_large.bend.snap index 9f7ea27e9..fefe7c825 100644 --- a/tests/snapshots/compile_file__number_too_large.bend.snap +++ b/tests/snapshots/compile_file__number_too_large.bend.snap @@ -3,6 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/number_too_large.bend --- Errors: -In tests/golden_tests/compile_file/number_too_large.bend : +In tests/golden_tests/compile_file/number_too_large.bend : Number literal outside of range for U24.  1 | main = 0x10000000 diff --git a/tests/snapshots/compile_file__ref_to_main.bend.snap b/tests/snapshots/compile_file__ref_to_main.bend.snap index d0d1bfb62..440a4d94b 100644 --- a/tests/snapshots/compile_file__ref_to_main.bend.snap +++ b/tests/snapshots/compile_file__ref_to_main.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/ref_to_main.bend --- Errors: +During execution : In definition 'Foo': Main definition can't be referenced inside the program. diff --git a/tests/snapshots/compile_file__repeated_bind_rule.bend.snap b/tests/snapshots/compile_file__repeated_bind_rule.bend.snap index d6fa3989d..246885b17 100644 --- a/tests/snapshots/compile_file__repeated_bind_rule.bend.snap +++ b/tests/snapshots/compile_file__repeated_bind_rule.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/repeated_bind_rule.bend --- Warnings: +In tests/golden_tests/compile_file/repeated_bind_rule.bend : In definition 'Foo': Repeated bind in pattern matching rule: 'a'. diff --git a/tests/snapshots/compile_file__switch_all_patterns.bend.snap b/tests/snapshots/compile_file__switch_all_patterns.bend.snap index 3478deee2..e28f72819 100644 --- a/tests/snapshots/compile_file__switch_all_patterns.bend.snap +++ b/tests/snapshots/compile_file__switch_all_patterns.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/switch_all_patterns.bend --- Errors: -In tests/golden_tests/compile_file/switch_all_patterns.bend : +In tests/golden_tests/compile_file/switch_all_patterns.bend : - expected: '0' - detected:  7 | _: x-1 diff --git a/tests/snapshots/compile_file__switch_incomplete.bend.snap b/tests/snapshots/compile_file__switch_incomplete.bend.snap index e12910f6d..e1963c608 100644 --- a/tests/snapshots/compile_file__switch_incomplete.bend.snap +++ b/tests/snapshots/compile_file__switch_incomplete.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/switch_incomplete.bend --- Errors: -In tests/golden_tests/compile_file/switch_incomplete.bend : +In tests/golden_tests/compile_file/switch_incomplete.bend : - expected: term - detected:  2 | main = switch {} diff --git a/tests/snapshots/compile_file__top_level_name_slashslash.bend.snap b/tests/snapshots/compile_file__top_level_name_slashslash.bend.snap index 058840a03..671f5a591 100644 --- a/tests/snapshots/compile_file__top_level_name_slashslash.bend.snap +++ b/tests/snapshots/compile_file__top_level_name_slashslash.bend.snap @@ -3,6 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/top_level_name_slashslash.bend --- Errors: -In tests/golden_tests/compile_file/top_level_name_slashslash.bend : +In tests/golden_tests/compile_file/top_level_name_slashslash.bend : Top-level names are not allowed to start with "//".  4 | def //thisshouldfail(): diff --git a/tests/snapshots/compile_file__unbound_unscoped_var.bend.snap b/tests/snapshots/compile_file__unbound_unscoped_var.bend.snap index 50012bebc..f338bc8b1 100644 --- a/tests/snapshots/compile_file__unbound_unscoped_var.bend.snap +++ b/tests/snapshots/compile_file__unbound_unscoped_var.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/unbound_unscoped_var.bend --- Errors: +In tests/golden_tests/compile_file/unbound_unscoped_var.bend : In definition 'main': Unbound unscoped variable '$a'. diff --git a/tests/snapshots/compile_file__unbound_var.bend.snap b/tests/snapshots/compile_file__unbound_var.bend.snap index a53e420c1..57558fd1b 100644 --- a/tests/snapshots/compile_file__unbound_var.bend.snap +++ b/tests/snapshots/compile_file__unbound_var.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/unbound_var.bend --- Errors: +In tests/golden_tests/compile_file/unbound_var.bend : In definition 'main': Unbound variable 'a'. diff --git a/tests/snapshots/compile_file__unbound_var_scope.bend.snap b/tests/snapshots/compile_file__unbound_var_scope.bend.snap index 2976e0743..26bdad031 100644 --- a/tests/snapshots/compile_file__unbound_var_scope.bend.snap +++ b/tests/snapshots/compile_file__unbound_var_scope.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/unbound_var_scope.bend --- Errors: +In tests/golden_tests/compile_file/unbound_var_scope.bend : In definition 'main': Unbound variable 'b'. diff --git a/tests/snapshots/compile_file__unbound_with_tup_pattern.bend.snap b/tests/snapshots/compile_file__unbound_with_tup_pattern.bend.snap index 549c276db..310955d13 100644 --- a/tests/snapshots/compile_file__unbound_with_tup_pattern.bend.snap +++ b/tests/snapshots/compile_file__unbound_with_tup_pattern.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/unbound_with_tup_pattern.bend --- Errors: +In tests/golden_tests/compile_file/unbound_with_tup_pattern.bend : In definition 'Foo': Unbound variable 'a'. diff --git a/tests/snapshots/compile_file__unexpected_top_char.bend.snap b/tests/snapshots/compile_file__unexpected_top_char.bend.snap index a847ea43f..73a648b3f 100644 --- a/tests/snapshots/compile_file__unexpected_top_char.bend.snap +++ b/tests/snapshots/compile_file__unexpected_top_char.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/unexpected_top_char.bend --- Errors: -In tests/golden_tests/compile_file/unexpected_top_char.bend : +In tests/golden_tests/compile_file/unexpected_top_char.bend : - expected: top-level definition - detected:  1 | * diff --git a/tests/snapshots/compile_file__unscoped_dup_use.bend.snap b/tests/snapshots/compile_file__unscoped_dup_use.bend.snap index 1c4ed17ce..14369581f 100644 --- a/tests/snapshots/compile_file__unscoped_dup_use.bend.snap +++ b/tests/snapshots/compile_file__unscoped_dup_use.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/unscoped_dup_use.bend --- Errors: +In tests/golden_tests/compile_file/unscoped_dup_use.bend : In definition 'main': Unscoped variable '$a' used more than once. diff --git a/tests/snapshots/compile_file__unused_unscoped_bind.bend.snap b/tests/snapshots/compile_file__unused_unscoped_bind.bend.snap index b2b5f265a..986661ae2 100644 --- a/tests/snapshots/compile_file__unused_unscoped_bind.bend.snap +++ b/tests/snapshots/compile_file__unused_unscoped_bind.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/unused_unscoped_bind.bend --- Errors: +In tests/golden_tests/compile_file/unused_unscoped_bind.bend : In definition 'main': Unscoped variable from lambda 'λ$a' is never used. diff --git a/tests/snapshots/compile_file__variable_name_double_underscore.bend.snap b/tests/snapshots/compile_file__variable_name_double_underscore.bend.snap index 667887ed5..75c737f84 100644 --- a/tests/snapshots/compile_file__variable_name_double_underscore.bend.snap +++ b/tests/snapshots/compile_file__variable_name_double_underscore.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/variable_name_double_underscore.bend --- Errors: -In tests/golden_tests/compile_file/variable_name_double_underscore.bend : +In tests/golden_tests/compile_file/variable_name_double_underscore.bend : - expected: expression - detected:  2 | return __this_should_fail__(*) diff --git a/tests/snapshots/compile_file__vicious_circles.bend.snap b/tests/snapshots/compile_file__vicious_circles.bend.snap index 4824d0655..924b0b4fb 100644 --- a/tests/snapshots/compile_file__vicious_circles.bend.snap +++ b/tests/snapshots/compile_file__vicious_circles.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/vicious_circles.bend --- Errors: +During execution : In compiled inet 'disconnected_self_lam': Found term that compiles into an inet with a vicious cycle In compiled inet 'dup_self': diff --git a/tests/snapshots/compile_file__warn_and_err.bend.snap b/tests/snapshots/compile_file__warn_and_err.bend.snap index 3e331175a..7bfd6e05f 100644 --- a/tests/snapshots/compile_file__warn_and_err.bend.snap +++ b/tests/snapshots/compile_file__warn_and_err.bend.snap @@ -3,9 +3,11 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/warn_and_err.bend --- Warnings: +In tests/golden_tests/compile_file/warn_and_err.bend : In definition 'Foo': Repeated bind in pattern matching rule: 'a'. Errors: +In tests/golden_tests/compile_file/warn_and_err.bend : In definition 'Main': Unbound variable 'a'. diff --git a/tests/snapshots/compile_file__with_clause_parse_err.bend.snap b/tests/snapshots/compile_file__with_clause_parse_err.bend.snap index 94e4475f7..9969ae9e0 100644 --- a/tests/snapshots/compile_file__with_clause_parse_err.bend.snap +++ b/tests/snapshots/compile_file__with_clause_parse_err.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/with_clause_parse_err.bend --- Errors: -In tests/golden_tests/compile_file/with_clause_parse_err.bend : +In tests/golden_tests/compile_file/with_clause_parse_err.bend : - expected: '{' - detected:  1 | main = @a @b switch b witha{ diff --git a/tests/snapshots/compile_file__wrong_ctr_arity.bend.snap b/tests/snapshots/compile_file__wrong_ctr_arity.bend.snap index 1f47876cd..a1cc9d9bc 100644 --- a/tests/snapshots/compile_file__wrong_ctr_arity.bend.snap +++ b/tests/snapshots/compile_file__wrong_ctr_arity.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/wrong_ctr_arity.bend --- Errors: +In tests/golden_tests/compile_file/wrong_ctr_arity.bend : In definition 'Bar': Incorrect arity for constructor 'Boxed/Box' of type 'Boxed' in pattern matching rule. Expected 1 fields, found 2 diff --git a/tests/snapshots/compile_file__wrong_ctr_var_arity.bend.snap b/tests/snapshots/compile_file__wrong_ctr_var_arity.bend.snap index 60591d401..2b6732e62 100644 --- a/tests/snapshots/compile_file__wrong_ctr_var_arity.bend.snap +++ b/tests/snapshots/compile_file__wrong_ctr_var_arity.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/wrong_ctr_var_arity.bend --- Errors: +In tests/golden_tests/compile_file/wrong_ctr_var_arity.bend : In definition 'foo': Incorrect arity for constructor 'Tup/pair' of type 'Tup' in pattern matching rule. Expected 2 fields, found 0 diff --git a/tests/snapshots/compile_file__wrong_nums.bend.snap b/tests/snapshots/compile_file__wrong_nums.bend.snap index f8a2a1533..caf34f8bc 100644 --- a/tests/snapshots/compile_file__wrong_nums.bend.snap +++ b/tests/snapshots/compile_file__wrong_nums.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/wrong_nums.bend --- Errors: -In tests/golden_tests/compile_file/wrong_nums.bend : +In tests/golden_tests/compile_file/wrong_nums.bend : - expected: valid binary digit - detected:  1 | main = (+ 0b012345 0FA) diff --git a/tests/snapshots/compile_file__wrong_unicode_escape.bend.snap b/tests/snapshots/compile_file__wrong_unicode_escape.bend.snap index 682d74204..42553937f 100644 --- a/tests/snapshots/compile_file__wrong_unicode_escape.bend.snap +++ b/tests/snapshots/compile_file__wrong_unicode_escape.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/wrong_unicode_escape.bend --- Errors: -In tests/golden_tests/compile_file/wrong_unicode_escape.bend : +In tests/golden_tests/compile_file/wrong_unicode_escape.bend : - expected: '}' - detected:  1 | main = (String.cons '\u{1' "\u2}\u{zxcx}") diff --git a/tests/snapshots/compile_file_o_all__adt_string.bend.snap b/tests/snapshots/compile_file_o_all__adt_string.bend.snap index f5d4470c6..c491410d8 100644 --- a/tests/snapshots/compile_file_o_all__adt_string.bend.snap +++ b/tests/snapshots/compile_file_o_all__adt_string.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/adt_string.bend --- Errors: -In tests/golden_tests/compile_file_o_all/adt_string.bend : +In tests/golden_tests/compile_file_o_all/adt_string.bend : Redefinition of builtin (type) 'String'.  1 | type String = S  2 |  diff --git a/tests/snapshots/compile_file_o_all__bad_parens_making_erased_let.bend.snap b/tests/snapshots/compile_file_o_all__bad_parens_making_erased_let.bend.snap index 726c4d9a4..ada4253c7 100644 --- a/tests/snapshots/compile_file_o_all__bad_parens_making_erased_let.bend.snap +++ b/tests/snapshots/compile_file_o_all__bad_parens_making_erased_let.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/bad_parens_making_erased_let.bend --- Errors: +In tests/golden_tests/compile_file_o_all/bad_parens_making_erased_let.bend : In definition 'main': Unbound variable 'two'. Unbound variable 'qua'. diff --git a/tests/snapshots/compile_file_o_all__cyclic_dup.bend.snap b/tests/snapshots/compile_file_o_all__cyclic_dup.bend.snap index 6114b7b49..7a95980d8 100644 --- a/tests/snapshots/compile_file_o_all__cyclic_dup.bend.snap +++ b/tests/snapshots/compile_file_o_all__cyclic_dup.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/cyclic_dup.bend --- Errors: +In tests/golden_tests/compile_file_o_all/cyclic_dup.bend : In definition 'main': Unbound variable 'y1'. diff --git a/tests/snapshots/compile_file_o_all__double_main.bend.snap b/tests/snapshots/compile_file_o_all__double_main.bend.snap index 8d14ad81e..2abfc54ce 100644 --- a/tests/snapshots/compile_file_o_all__double_main.bend.snap +++ b/tests/snapshots/compile_file_o_all__double_main.bend.snap @@ -3,4 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/double_main.bend --- Errors: +During execution : File has both 'main' and 'Main' definitions. diff --git a/tests/snapshots/compile_file_o_all__match_adt_non_exhaustive.bend.snap b/tests/snapshots/compile_file_o_all__match_adt_non_exhaustive.bend.snap index b3463d452..e1ddd5deb 100644 --- a/tests/snapshots/compile_file_o_all__match_adt_non_exhaustive.bend.snap +++ b/tests/snapshots/compile_file_o_all__match_adt_non_exhaustive.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/match_adt_non_exhaustive.bend --- Errors: +In tests/golden_tests/compile_file_o_all/match_adt_non_exhaustive.bend : In definition 'main': Non-exhaustive 'match' expression of type 'Maybe'. Case 'Maybe/Some' not covered. diff --git a/tests/snapshots/compile_file_o_all__non_exhaustive_and.bend.snap b/tests/snapshots/compile_file_o_all__non_exhaustive_and.bend.snap index 84cd4c29b..d75690cbd 100644 --- a/tests/snapshots/compile_file_o_all__non_exhaustive_and.bend.snap +++ b/tests/snapshots/compile_file_o_all__non_exhaustive_and.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/non_exhaustive_and.bend --- Errors: +In tests/golden_tests/compile_file_o_all/non_exhaustive_and.bend : In definition 'Bool.and': Non-exhaustive pattern matching rule. Constructor 'Bool/F' of type 'Bool' not covered diff --git a/tests/snapshots/compile_file_o_all__non_exhaustive_different_types.bend.snap b/tests/snapshots/compile_file_o_all__non_exhaustive_different_types.bend.snap index 2ced975ff..44e9f6202 100644 --- a/tests/snapshots/compile_file_o_all__non_exhaustive_different_types.bend.snap +++ b/tests/snapshots/compile_file_o_all__non_exhaustive_different_types.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/non_exhaustive_different_types.bend --- Errors: +In tests/golden_tests/compile_file_o_all/non_exhaustive_different_types.bend : In definition 'foo': Non-exhaustive pattern matching rule. Constructor 'b3/t3' of type 'b3' not covered diff --git a/tests/snapshots/compile_file_o_all__non_exhaustive_pattern.bend.snap b/tests/snapshots/compile_file_o_all__non_exhaustive_pattern.bend.snap index 0e73f2e07..a9a6ef2e1 100644 --- a/tests/snapshots/compile_file_o_all__non_exhaustive_pattern.bend.snap +++ b/tests/snapshots/compile_file_o_all__non_exhaustive_pattern.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/non_exhaustive_pattern.bend --- Errors: +In tests/golden_tests/compile_file_o_all/non_exhaustive_pattern.bend : In definition 'Foo': Non-exhaustive pattern matching rule. Constructor 'Type/A' of type 'Type' not covered diff --git a/tests/snapshots/compile_file_o_all__non_exhaustive_tree.bend.snap b/tests/snapshots/compile_file_o_all__non_exhaustive_tree.bend.snap index dca4a8145..90327fd2f 100644 --- a/tests/snapshots/compile_file_o_all__non_exhaustive_tree.bend.snap +++ b/tests/snapshots/compile_file_o_all__non_exhaustive_tree.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/non_exhaustive_tree.bend --- Errors: +In tests/golden_tests/compile_file_o_all/non_exhaustive_tree.bend : In definition 'Warp': Non-exhaustive pattern matching rule. Constructor 'Tree/Leaf' of type 'Tree' not covered diff --git a/tests/snapshots/compile_file_o_all__repeated_name_trucation.bend.snap b/tests/snapshots/compile_file_o_all__repeated_name_trucation.bend.snap index 6265818d5..014737cea 100644 --- a/tests/snapshots/compile_file_o_all__repeated_name_trucation.bend.snap +++ b/tests/snapshots/compile_file_o_all__repeated_name_trucation.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/repeated_name_trucation.bend --- Warnings: +During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * long_name_that_truncates -> long_name_that_truncates diff --git a/tests/snapshots/compile_file_o_all__self_ref.bend.snap b/tests/snapshots/compile_file_o_all__self_ref.bend.snap index 0ba6fcd03..75efad5e3 100644 --- a/tests/snapshots/compile_file_o_all__self_ref.bend.snap +++ b/tests/snapshots/compile_file_o_all__self_ref.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/self_ref.bend --- Warnings: +During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * Foo -> Foo @@ -32,5 +33,6 @@ To disable this check, use the "-Arecursion-cycle" compiler option. Errors: +During execution : During inlining: infinite reference cycle in `@Foo` diff --git a/tests/snapshots/compile_file_o_all__tagged_dup.bend.snap b/tests/snapshots/compile_file_o_all__tagged_dup.bend.snap index a2ba6e42f..e22c0d777 100644 --- a/tests/snapshots/compile_file_o_all__tagged_dup.bend.snap +++ b/tests/snapshots/compile_file_o_all__tagged_dup.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/tagged_dup.bend --- Errors: -In tests/golden_tests/compile_file_o_all/tagged_dup.bend : +In tests/golden_tests/compile_file_o_all/tagged_dup.bend : - expected: '=' - detected:  4 | let #i {e f} = @x x; diff --git a/tests/snapshots/compile_file_o_all__tagged_lam.bend.snap b/tests/snapshots/compile_file_o_all__tagged_lam.bend.snap index d76c7274b..f2b735c90 100644 --- a/tests/snapshots/compile_file_o_all__tagged_lam.bend.snap +++ b/tests/snapshots/compile_file_o_all__tagged_lam.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/tagged_lam.bend --- Errors: -In tests/golden_tests/compile_file_o_all/tagged_lam.bend : +In tests/golden_tests/compile_file_o_all/tagged_lam.bend : - expected: term - detected: end of input  2 |   diff --git a/tests/snapshots/compile_file_o_all__tagged_sup.bend.snap b/tests/snapshots/compile_file_o_all__tagged_sup.bend.snap index d6a53503d..8b8c76fa7 100644 --- a/tests/snapshots/compile_file_o_all__tagged_sup.bend.snap +++ b/tests/snapshots/compile_file_o_all__tagged_sup.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/tagged_sup.bend --- Errors: -In tests/golden_tests/compile_file_o_all/tagged_sup.bend : +In tests/golden_tests/compile_file_o_all/tagged_sup.bend : - expected: top-level definition - detected:  2 | b = #i {λx x λx x} diff --git a/tests/snapshots/compile_file_o_no_all__bitonic_sort.bend.snap b/tests/snapshots/compile_file_o_no_all__bitonic_sort.bend.snap index 187767b96..195994ba7 100644 --- a/tests/snapshots/compile_file_o_no_all__bitonic_sort.bend.snap +++ b/tests/snapshots/compile_file_o_no_all__bitonic_sort.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_no_all/bitonic_sort.bend --- Errors: +During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * Down -> Flow -> Down * Warp -> Warp diff --git a/tests/snapshots/compile_file_o_no_all__list_reverse.bend.snap b/tests/snapshots/compile_file_o_no_all__list_reverse.bend.snap index bc27b2d7b..3625f7ff5 100644 --- a/tests/snapshots/compile_file_o_no_all__list_reverse.bend.snap +++ b/tests/snapshots/compile_file_o_no_all__list_reverse.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_no_all/list_reverse.bend --- Errors: +During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * concat -> concat * reverse -> reverse diff --git a/tests/snapshots/compile_file_o_no_all__sum_tree.bend.snap b/tests/snapshots/compile_file_o_no_all__sum_tree.bend.snap index b7c2f6eb6..14b4c93ba 100644 --- a/tests/snapshots/compile_file_o_no_all__sum_tree.bend.snap +++ b/tests/snapshots/compile_file_o_no_all__sum_tree.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_no_all/sum_tree.bend --- Errors: +During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * gen -> gen * sum -> sum diff --git a/tests/snapshots/compile_long__huge_tree.bend.snap b/tests/snapshots/compile_long__huge_tree.bend.snap index ee6c230f5..cee2bb6fd 100644 --- a/tests/snapshots/compile_long__huge_tree.bend.snap +++ b/tests/snapshots/compile_long__huge_tree.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_long/huge_tree.bend --- Errors: +During execution : In definition 'main': Definition is too large for HVM C (size=120002, max size=4095). Please break it into smaller pieces. diff --git a/tests/snapshots/compile_long__long_str_file.bend.snap b/tests/snapshots/compile_long__long_str_file.bend.snap index b4e9f10d8..28ee629ac 100644 --- a/tests/snapshots/compile_long__long_str_file.bend.snap +++ b/tests/snapshots/compile_long__long_str_file.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_long/long_str_file.bend --- Errors: +During execution : In definition 'main': Definition is too large for HVM C (size=1461028, max size=4095). Please break it into smaller pieces. diff --git a/tests/snapshots/desugar_file__non_exaustive_limit.bend.snap b/tests/snapshots/desugar_file__non_exaustive_limit.bend.snap index f19cb796f..72a3dd7e7 100644 --- a/tests/snapshots/desugar_file__non_exaustive_limit.bend.snap +++ b/tests/snapshots/desugar_file__non_exaustive_limit.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/desugar_file/non_exaustive_limit.bend --- Errors: +In tests/golden_tests/desugar_file/non_exaustive_limit.bend : In definition 'Bar': Non-exhaustive pattern matching rule. Constructor 'Foo/B' of type 'Foo' not covered diff --git a/tests/snapshots/import_system__import_main.bend.snap b/tests/snapshots/import_system__import_main.bend.snap index c058f3a3d..074c947b3 100644 --- a/tests/snapshots/import_system__import_main.bend.snap +++ b/tests/snapshots/import_system__import_main.bend.snap @@ -3,4 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/import_main.bend --- Errors: +During execution : Can not import the entry point of the program. diff --git a/tests/snapshots/import_system__import_main2.bend.snap b/tests/snapshots/import_system__import_main2.bend.snap index 698bbe8f3..5fbc9d195 100644 --- a/tests/snapshots/import_system__import_main2.bend.snap +++ b/tests/snapshots/import_system__import_main2.bend.snap @@ -3,4 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/import_main2.bend --- Errors: +During execution : Can not import the entry point of the program. diff --git a/tests/snapshots/import_system__import_main3.bend.snap b/tests/snapshots/import_system__import_main3.bend.snap index f00d33137..22138df46 100644 --- a/tests/snapshots/import_system__import_main3.bend.snap +++ b/tests/snapshots/import_system__import_main3.bend.snap @@ -3,4 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/import_main3.bend --- Errors: +During execution : Can not import the entry point of the program. diff --git a/tests/snapshots/import_system__imports_alias_shadow.bend.snap b/tests/snapshots/import_system__imports_alias_shadow.bend.snap index 1c6942786..ea8489fe6 100644 --- a/tests/snapshots/import_system__imports_alias_shadow.bend.snap +++ b/tests/snapshots/import_system__imports_alias_shadow.bend.snap @@ -3,4 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/imports_alias_shadow.bend --- Errors: +During execution : The import 'lib/nums/two' shadows the imported name 'lib/nums/one' diff --git a/tests/snapshots/import_system__imports_conflict.bend.snap b/tests/snapshots/import_system__imports_conflict.bend.snap index f651bdd44..15d5f9dd5 100644 --- a/tests/snapshots/import_system__imports_conflict.bend.snap +++ b/tests/snapshots/import_system__imports_conflict.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/imports_conflict.bend --- Errors: +During execution : The imported definition 'lib/a/b/C' conflicts with the definition 'lib/a/b/C'. The imported constructor 'lib/a/b/C' conflicts with the definition 'lib/a/b/C'. diff --git a/tests/snapshots/import_system__imports_file_and_dir_conflict.bend.snap b/tests/snapshots/import_system__imports_file_and_dir_conflict.bend.snap index 4c28d7844..3d9e0efda 100644 --- a/tests/snapshots/import_system__imports_file_and_dir_conflict.bend.snap +++ b/tests/snapshots/import_system__imports_file_and_dir_conflict.bend.snap @@ -3,4 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/imports_file_and_dir_conflict.bend --- Errors: +During execution : Both file 'lib/file_and_dir.bend' and folder 'lib/file_and_dir' contains the import 'w' diff --git a/tests/snapshots/import_system__imports_shadow.bend.snap b/tests/snapshots/import_system__imports_shadow.bend.snap index 284db8136..34fee2cb7 100644 --- a/tests/snapshots/import_system__imports_shadow.bend.snap +++ b/tests/snapshots/import_system__imports_shadow.bend.snap @@ -3,4 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/imports_shadow.bend --- Errors: +During execution : The import 'lib/myFun/myFun' shadows the imported name 'lib/folder/myFun/myFun' diff --git a/tests/snapshots/import_system__imports_shadow2.bend.snap b/tests/snapshots/import_system__imports_shadow2.bend.snap index 85e37d51d..eb96db7fe 100644 --- a/tests/snapshots/import_system__imports_shadow2.bend.snap +++ b/tests/snapshots/import_system__imports_shadow2.bend.snap @@ -3,4 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/imports_shadow2.bend --- Errors: +During execution : The import 'lib/folder/myFun/myFun' shadows the imported name 'lib/myFun/myFun' diff --git a/tests/snapshots/mutual_recursion__a_b_c.bend.snap b/tests/snapshots/mutual_recursion__a_b_c.bend.snap index 7a8d139a8..7c3ef16fd 100644 --- a/tests/snapshots/mutual_recursion__a_b_c.bend.snap +++ b/tests/snapshots/mutual_recursion__a_b_c.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/mutual_recursion/a_b_c.bend --- Errors: +During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * A -> B -> C -> A diff --git a/tests/snapshots/mutual_recursion__merged.bend.snap b/tests/snapshots/mutual_recursion__merged.bend.snap index 739cfb0b9..cdcb0d945 100644 --- a/tests/snapshots/mutual_recursion__merged.bend.snap +++ b/tests/snapshots/mutual_recursion__merged.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/mutual_recursion/merged.bend --- Errors: +During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * Rec -> X -> Rec * Rec -> Y -> Rec diff --git a/tests/snapshots/mutual_recursion__multiple.bend.snap b/tests/snapshots/mutual_recursion__multiple.bend.snap index 4605f2486..65a93e8a8 100644 --- a/tests/snapshots/mutual_recursion__multiple.bend.snap +++ b/tests/snapshots/mutual_recursion__multiple.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/mutual_recursion/multiple.bend --- Errors: +During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * A -> B -> C -> A * H -> I -> H diff --git a/tests/snapshots/mutual_recursion__odd_even.bend.snap b/tests/snapshots/mutual_recursion__odd_even.bend.snap index 4d8ea8667..64a3610d2 100644 --- a/tests/snapshots/mutual_recursion__odd_even.bend.snap +++ b/tests/snapshots/mutual_recursion__odd_even.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/mutual_recursion/odd_even.bend --- Errors: +During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * isEven -> isOdd -> isEven diff --git a/tests/snapshots/parse_file__bad_floating.bend.snap b/tests/snapshots/parse_file__bad_floating.bend.snap index 08a1de753..bacd0e93f 100644 --- a/tests/snapshots/parse_file__bad_floating.bend.snap +++ b/tests/snapshots/parse_file__bad_floating.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/bad_floating.bend --- Errors: -In tests/golden_tests/parse_file/bad_floating.bend : +In tests/golden_tests/parse_file/bad_floating.bend : - expected: newline - detected:  2 | return 0xA.0xA diff --git a/tests/snapshots/parse_file__bend_missing_else.bend.snap b/tests/snapshots/parse_file__bend_missing_else.bend.snap index e00a8c9fd..3da8c38cb 100644 --- a/tests/snapshots/parse_file__bend_missing_else.bend.snap +++ b/tests/snapshots/parse_file__bend_missing_else.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/bend_missing_else.bend --- Errors: -In tests/golden_tests/parse_file/bend_missing_else.bend : +In tests/golden_tests/parse_file/bend_missing_else.bend : - expected: 'else' - detected:  14 | def main(): diff --git a/tests/snapshots/parse_file__fold_missing_case.bend.snap b/tests/snapshots/parse_file__fold_missing_case.bend.snap index 81926ecc5..362af2f63 100644 --- a/tests/snapshots/parse_file__fold_missing_case.bend.snap +++ b/tests/snapshots/parse_file__fold_missing_case.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/fold_missing_case.bend --- Errors: -In tests/golden_tests/parse_file/fold_missing_case.bend : +In tests/golden_tests/parse_file/fold_missing_case.bend : - expected: 'case' - detected: end of input  4 |   diff --git a/tests/snapshots/parse_file__fun_def_name.bend.snap b/tests/snapshots/parse_file__fun_def_name.bend.snap index 996c633f5..e2a6af2e6 100644 --- a/tests/snapshots/parse_file__fun_def_name.bend.snap +++ b/tests/snapshots/parse_file__fun_def_name.bend.snap @@ -3,6 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/fun_def_name.bend --- Errors: -In tests/golden_tests/parse_file/fun_def_name.bend : +In tests/golden_tests/parse_file/fun_def_name.bend : Expected a rule with name 'aux'.  4 | aux2 (List/Cons head tail) = (+ head (aux tail)) diff --git a/tests/snapshots/parse_file__if_missing_else.bend.snap b/tests/snapshots/parse_file__if_missing_else.bend.snap index 8756e211d..c5b35e0f4 100644 --- a/tests/snapshots/parse_file__if_missing_else.bend.snap +++ b/tests/snapshots/parse_file__if_missing_else.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/if_missing_else.bend --- Errors: -In tests/golden_tests/parse_file/if_missing_else.bend : +In tests/golden_tests/parse_file/if_missing_else.bend : - expected: 'else' or 'elif' - detected: end of input  5 |   diff --git a/tests/snapshots/parse_file__match_missing_case.bend.snap b/tests/snapshots/parse_file__match_missing_case.bend.snap index 5c7ad9e29..700673b10 100644 --- a/tests/snapshots/parse_file__match_missing_case.bend.snap +++ b/tests/snapshots/parse_file__match_missing_case.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/match_missing_case.bend --- Errors: -In tests/golden_tests/parse_file/match_missing_case.bend : +In tests/golden_tests/parse_file/match_missing_case.bend : - expected: 'case' - detected: end of input  4 |   diff --git a/tests/snapshots/parse_file__redefinition_builtin.bend.snap b/tests/snapshots/parse_file__redefinition_builtin.bend.snap index 8d444e7fb..ee51c4004 100644 --- a/tests/snapshots/parse_file__redefinition_builtin.bend.snap +++ b/tests/snapshots/parse_file__redefinition_builtin.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/redefinition_builtin.bend --- Errors: -In tests/golden_tests/parse_file/redefinition_builtin.bend : +In tests/golden_tests/parse_file/redefinition_builtin.bend : Redefinition of builtin (function) 'Map/get'.  1 | def Map/get(m):  2 |  return m diff --git a/tests/snapshots/parse_file__redefinition_ctr_with_fun.bend.snap b/tests/snapshots/parse_file__redefinition_ctr_with_fun.bend.snap index 04f507209..5c6e24669 100644 --- a/tests/snapshots/parse_file__redefinition_ctr_with_fun.bend.snap +++ b/tests/snapshots/parse_file__redefinition_ctr_with_fun.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/redefinition_ctr_with_fun.bend --- Errors: -In tests/golden_tests/parse_file/redefinition_ctr_with_fun.bend : +In tests/golden_tests/parse_file/redefinition_ctr_with_fun.bend : Redefinition of builtin (constructor) 'String/Cons'.  1 | def String/Cons(x):  2 |  return x diff --git a/tests/snapshots/parse_file__redefinition_fun_imp.bend.snap b/tests/snapshots/parse_file__redefinition_fun_imp.bend.snap index 01b3a8b59..b31d21b8a 100644 --- a/tests/snapshots/parse_file__redefinition_fun_imp.bend.snap +++ b/tests/snapshots/parse_file__redefinition_fun_imp.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/redefinition_fun_imp.bend --- Errors: -In tests/golden_tests/parse_file/redefinition_fun_imp.bend : +In tests/golden_tests/parse_file/redefinition_fun_imp.bend : Redefinition of function 'A'.  3 | def A:  4 |  return 0 diff --git a/tests/snapshots/parse_file__redefinition_imp_fun.bend.snap b/tests/snapshots/parse_file__redefinition_imp_fun.bend.snap index 39d574ed1..da1ddb800 100644 --- a/tests/snapshots/parse_file__redefinition_imp_fun.bend.snap +++ b/tests/snapshots/parse_file__redefinition_imp_fun.bend.snap @@ -3,6 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/redefinition_imp_fun.bend --- Errors: -In tests/golden_tests/parse_file/redefinition_imp_fun.bend : +In tests/golden_tests/parse_file/redefinition_imp_fun.bend : Redefinition of function 'A'.  5 | (A) = 1 diff --git a/tests/snapshots/parse_file__redefinition_type_with_object.bend.snap b/tests/snapshots/parse_file__redefinition_type_with_object.bend.snap index 18d84fd3d..189f008db 100644 --- a/tests/snapshots/parse_file__redefinition_type_with_object.bend.snap +++ b/tests/snapshots/parse_file__redefinition_type_with_object.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/redefinition_type_with_object.bend --- Errors: -In tests/golden_tests/parse_file/redefinition_type_with_object.bend : +In tests/golden_tests/parse_file/redefinition_type_with_object.bend : Redefinition of builtin (type) 'IO'.  1 | object IO { run }  diff --git a/tests/snapshots/parse_file__redefinition_with_def_between.bend.snap b/tests/snapshots/parse_file__redefinition_with_def_between.bend.snap index 25c124613..807d09e32 100644 --- a/tests/snapshots/parse_file__redefinition_with_def_between.bend.snap +++ b/tests/snapshots/parse_file__redefinition_with_def_between.bend.snap @@ -3,6 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/redefinition_with_def_between.bend --- Errors: -In tests/golden_tests/parse_file/redefinition_with_def_between.bend : +In tests/golden_tests/parse_file/redefinition_with_def_between.bend : Redefinition of function 'A'.  4 | (A) = @x x diff --git a/tests/snapshots/parse_file__redefinition_with_object_between.bend.snap b/tests/snapshots/parse_file__redefinition_with_object_between.bend.snap index 707c7f137..005d6a4a2 100644 --- a/tests/snapshots/parse_file__redefinition_with_object_between.bend.snap +++ b/tests/snapshots/parse_file__redefinition_with_object_between.bend.snap @@ -3,6 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/redefinition_with_object_between.bend --- Errors: -In tests/golden_tests/parse_file/redefinition_with_object_between.bend : +In tests/golden_tests/parse_file/redefinition_with_object_between.bend : Redefinition of function 'A'.  3 | A = 1 diff --git a/tests/snapshots/parse_file__redefinition_with_type_between.bend.snap b/tests/snapshots/parse_file__redefinition_with_type_between.bend.snap index ccdc4328f..7280f6a08 100644 --- a/tests/snapshots/parse_file__redefinition_with_type_between.bend.snap +++ b/tests/snapshots/parse_file__redefinition_with_type_between.bend.snap @@ -3,6 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/redefinition_with_type_between.bend --- Errors: -In tests/golden_tests/parse_file/redefinition_with_type_between.bend : +In tests/golden_tests/parse_file/redefinition_with_type_between.bend : Redefinition of function 'A'.  3 | A = 1 diff --git a/tests/snapshots/parse_file__repeated_adt_name.bend.snap b/tests/snapshots/parse_file__repeated_adt_name.bend.snap index 0caef38e2..434fc2a0c 100644 --- a/tests/snapshots/parse_file__repeated_adt_name.bend.snap +++ b/tests/snapshots/parse_file__repeated_adt_name.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/repeated_adt_name.bend --- Errors: -In tests/golden_tests/parse_file/repeated_adt_name.bend : +In tests/golden_tests/parse_file/repeated_adt_name.bend : Redefinition of type 'Foo'.  2 | type Foo = B  3 |  diff --git a/tests/snapshots/parse_file__repeated_datatype_name.bend.snap b/tests/snapshots/parse_file__repeated_datatype_name.bend.snap index 59acfd920..8e23b5667 100644 --- a/tests/snapshots/parse_file__repeated_datatype_name.bend.snap +++ b/tests/snapshots/parse_file__repeated_datatype_name.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/repeated_datatype_name.bend --- Errors: -In tests/golden_tests/parse_file/repeated_datatype_name.bend : +In tests/golden_tests/parse_file/repeated_datatype_name.bend : - information: Found a repeated field 'Expr' in constructor Expr/Plus. - location:  3 | | (Plus Expr Expr) diff --git a/tests/snapshots/parse_file__strange_pattern.bend.snap b/tests/snapshots/parse_file__strange_pattern.bend.snap index e15daa07b..70c43138f 100644 --- a/tests/snapshots/parse_file__strange_pattern.bend.snap +++ b/tests/snapshots/parse_file__strange_pattern.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/strange_pattern.bend --- Errors: -In tests/golden_tests/parse_file/strange_pattern.bend : +In tests/golden_tests/parse_file/strange_pattern.bend : - expected: pattern or '=' - detected:  1 | main & = (a b c) diff --git a/tests/snapshots/parse_file__tab.bend.snap b/tests/snapshots/parse_file__tab.bend.snap index 22c0aa835..a41337cec 100644 --- a/tests/snapshots/parse_file__tab.bend.snap +++ b/tests/snapshots/parse_file__tab.bend.snap @@ -3,6 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/tab.bend --- Errors: -In tests/golden_tests/parse_file/tab.bend : +In tests/golden_tests/parse_file/tab.bend : Tabs are not accepted for indentation.  2 |  x = 2 diff --git a/tests/snapshots/parse_file__tuple_need_parens.bend.snap b/tests/snapshots/parse_file__tuple_need_parens.bend.snap index 61bf25ac6..17e7cd8fc 100644 --- a/tests/snapshots/parse_file__tuple_need_parens.bend.snap +++ b/tests/snapshots/parse_file__tuple_need_parens.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/parse_file/tuple_need_parens.bend --- Errors: -In tests/golden_tests/parse_file/tuple_need_parens.bend : +In tests/golden_tests/parse_file/tuple_need_parens.bend : - expected: ':' - detected:  2 | if 1, 2: diff --git a/tests/snapshots/readback_hvm__bad_net.bend.snap b/tests/snapshots/readback_hvm__bad_net.bend.snap index af03cc7cc..0bc29607d 100644 --- a/tests/snapshots/readback_hvm__bad_net.bend.snap +++ b/tests/snapshots/readback_hvm__bad_net.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/readback_hvm/bad_net.bend --- Warnings: +During execution : During readback: Unable to interpret the HVM result as a valid Bend term. (Reached Root) diff --git a/tests/snapshots/readback_hvm__invalid_op2_op2.bend.snap b/tests/snapshots/readback_hvm__invalid_op2_op2.bend.snap index 930777230..6432cf894 100644 --- a/tests/snapshots/readback_hvm__invalid_op2_op2.bend.snap +++ b/tests/snapshots/readback_hvm__invalid_op2_op2.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/readback_hvm/invalid_op2_op2.bend --- Warnings: +During execution : During readback: Encountered an invalid numeric operation. (3 occurrences) diff --git a/tests/snapshots/run_file__360_no_scope.bend.snap b/tests/snapshots/run_file__360_no_scope.bend.snap index 377c47cec..b3767b0a3 100644 --- a/tests/snapshots/run_file__360_no_scope.bend.snap +++ b/tests/snapshots/run_file__360_no_scope.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/360_no_scope.bend --- Errors: -In tests/golden_tests/run_file/360_no_scope.bend : +In tests/golden_tests/run_file/360_no_scope.bend : - expected: '=' - detected: end of input  6 |   diff --git a/tests/snapshots/run_file__adt_match_wrong_tag.bend.snap b/tests/snapshots/run_file__adt_match_wrong_tag.bend.snap index 3de3d1f92..c5e00e445 100644 --- a/tests/snapshots/run_file__adt_match_wrong_tag.bend.snap +++ b/tests/snapshots/run_file__adt_match_wrong_tag.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/adt_match_wrong_tag.bend --- Errors: -In tests/golden_tests/run_file/adt_match_wrong_tag.bend : +In tests/golden_tests/run_file/adt_match_wrong_tag.bend : - expected: term - detected: end of input  4 |   diff --git a/tests/snapshots/run_file__adt_wrong_tag.bend.snap b/tests/snapshots/run_file__adt_wrong_tag.bend.snap index 6de0184ea..548d7d018 100644 --- a/tests/snapshots/run_file__adt_wrong_tag.bend.snap +++ b/tests/snapshots/run_file__adt_wrong_tag.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/adt_wrong_tag.bend --- Errors: -In tests/golden_tests/run_file/adt_wrong_tag.bend : +In tests/golden_tests/run_file/adt_wrong_tag.bend : - expected: term - detected: end of input  4 |   diff --git a/tests/snapshots/run_file__def_bool_num.bend.snap b/tests/snapshots/run_file__def_bool_num.bend.snap index 27dbe0f04..5e3846d7a 100644 --- a/tests/snapshots/run_file__def_bool_num.bend.snap +++ b/tests/snapshots/run_file__def_bool_num.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/def_bool_num.bend --- Errors: +In tests/golden_tests/run_file/def_bool_num.bend : In definition 'go': Non-exhaustive pattern matching rule. Default case of number type not covered. diff --git a/tests/snapshots/run_file__def_num_bool.bend.snap b/tests/snapshots/run_file__def_num_bool.bend.snap index 420ccdb91..769d29c15 100644 --- a/tests/snapshots/run_file__def_num_bool.bend.snap +++ b/tests/snapshots/run_file__def_num_bool.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/def_num_bool.bend --- Errors: +In tests/golden_tests/run_file/def_num_bool.bend : In definition 'go': Non-exhaustive pattern matching rule. Default case of number type not covered. diff --git a/tests/snapshots/run_file__empty.bend.snap b/tests/snapshots/run_file__empty.bend.snap index ae0322092..7b6c2c060 100644 --- a/tests/snapshots/run_file__empty.bend.snap +++ b/tests/snapshots/run_file__empty.bend.snap @@ -3,4 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/empty.bend --- Errors: +During execution : File has no 'main' definition. diff --git a/tests/snapshots/run_file__exp.bend.snap b/tests/snapshots/run_file__exp.bend.snap index ca80eb038..bb4d68a7f 100644 --- a/tests/snapshots/run_file__exp.bend.snap +++ b/tests/snapshots/run_file__exp.bend.snap @@ -4,6 +4,7 @@ input_file: tests/golden_tests/run_file/exp.bend --- NumScott: Warnings: +During execution : During readback: Unable to interpret the HVM result as a valid Bend term. (Reached Root) @@ -11,6 +12,7 @@ NumScott: Scott: Warnings: +During execution : During readback: Unable to interpret the HVM result as a valid Bend term. (Reached Root) diff --git a/tests/snapshots/run_file__let_tup_readback.bend.snap b/tests/snapshots/run_file__let_tup_readback.bend.snap index 662ee8a9e..df9e7629b 100644 --- a/tests/snapshots/run_file__let_tup_readback.bend.snap +++ b/tests/snapshots/run_file__let_tup_readback.bend.snap @@ -4,6 +4,7 @@ input_file: tests/golden_tests/run_file/let_tup_readback.bend --- NumScott: Warnings: +During execution : During readback: Unable to interpret the HVM result as a valid Bend term. (Reached Root) @@ -11,6 +12,7 @@ NumScott: Scott: Warnings: +During execution : During readback: Unable to interpret the HVM result as a valid Bend term. (Reached Root) diff --git a/tests/snapshots/run_file__match_sup.bend.snap b/tests/snapshots/run_file__match_sup.bend.snap index 99a099b12..9db5fccfa 100644 --- a/tests/snapshots/run_file__match_sup.bend.snap +++ b/tests/snapshots/run_file__match_sup.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/match_sup.bend --- Errors: -In tests/golden_tests/run_file/match_sup.bend : +In tests/golden_tests/run_file/match_sup.bend : - expected: term - detected: end of input  7 |   diff --git a/tests/snapshots/run_file__match_vars.bend.snap b/tests/snapshots/run_file__match_vars.bend.snap index 866c9aefa..173e62ae2 100644 --- a/tests/snapshots/run_file__match_vars.bend.snap +++ b/tests/snapshots/run_file__match_vars.bend.snap @@ -3,6 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/match_vars.bend --- Errors: +In tests/golden_tests/run_file/match_vars.bend : In definition 'main': Irrefutable 'match' expression. All cases after variable pattern 'true' will be ignored. Note that to use a 'match' expression, the matched constructors need to be defined in a 'data' definition. diff --git a/tests/snapshots/run_file__nat_add.bend.snap b/tests/snapshots/run_file__nat_add.bend.snap index 31b36eaae..f2a2dc696 100644 --- a/tests/snapshots/run_file__nat_add.bend.snap +++ b/tests/snapshots/run_file__nat_add.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/nat_add.bend --- Errors: -In tests/golden_tests/run_file/nat_add.bend : +In tests/golden_tests/run_file/nat_add.bend : - expected: term - detected: end of input  5 |   diff --git a/tests/snapshots/run_file__nat_add_num.bend.snap b/tests/snapshots/run_file__nat_add_num.bend.snap index 343188ce8..5f333b67b 100644 --- a/tests/snapshots/run_file__nat_add_num.bend.snap +++ b/tests/snapshots/run_file__nat_add_num.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/nat_add_num.bend --- Errors: -In tests/golden_tests/run_file/nat_add_num.bend : +In tests/golden_tests/run_file/nat_add_num.bend : - expected: term - detected: end of input  5 |   diff --git a/tests/snapshots/run_file__num_match_missing_var.bend.snap b/tests/snapshots/run_file__num_match_missing_var.bend.snap index 1fb2700cc..eac6d9c5a 100644 --- a/tests/snapshots/run_file__num_match_missing_var.bend.snap +++ b/tests/snapshots/run_file__num_match_missing_var.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/num_match_missing_var.bend --- Errors: -In tests/golden_tests/run_file/num_match_missing_var.bend : +In tests/golden_tests/run_file/num_match_missing_var.bend : - expected: '}' - detected:  7 | _: f diff --git a/tests/snapshots/run_file__open_too_many_ctrs.bend.snap b/tests/snapshots/run_file__open_too_many_ctrs.bend.snap index 5cc1c09f6..8e6a53f97 100644 --- a/tests/snapshots/run_file__open_too_many_ctrs.bend.snap +++ b/tests/snapshots/run_file__open_too_many_ctrs.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/open_too_many_ctrs.bend --- Errors: +In tests/golden_tests/run_file/open_too_many_ctrs.bend : In definition 'main': Type 'MyTree' of an 'open' has more than one constructor diff --git a/tests/snapshots/run_file__open_undefined_type.bend.snap b/tests/snapshots/run_file__open_undefined_type.bend.snap index a942c18d9..73df03a33 100644 --- a/tests/snapshots/run_file__open_undefined_type.bend.snap +++ b/tests/snapshots/run_file__open_undefined_type.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/open_undefined_type.bend --- Errors: +In tests/golden_tests/run_file/open_undefined_type.bend : In definition 'main': Type 'MyType' of an 'open' is not defined diff --git a/tests/snapshots/run_file__override_list_ctr.bend.snap b/tests/snapshots/run_file__override_list_ctr.bend.snap index a0b5243a2..789f8c5ef 100644 --- a/tests/snapshots/run_file__override_list_ctr.bend.snap +++ b/tests/snapshots/run_file__override_list_ctr.bend.snap @@ -3,6 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/override_list_ctr.bend --- Errors: -In tests/golden_tests/run_file/override_list_ctr.bend : +In tests/golden_tests/run_file/override_list_ctr.bend : Redefinition of builtin (constructor) 'List/Nil'.  1 | List/Nil = * diff --git a/tests/snapshots/run_file__override_str_ctr.bend.snap b/tests/snapshots/run_file__override_str_ctr.bend.snap index 995b1c5d4..34d01367a 100644 --- a/tests/snapshots/run_file__override_str_ctr.bend.snap +++ b/tests/snapshots/run_file__override_str_ctr.bend.snap @@ -3,6 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/override_str_ctr.bend --- Errors: -In tests/golden_tests/run_file/override_str_ctr.bend : +In tests/golden_tests/run_file/override_str_ctr.bend : Redefinition of builtin (constructor) 'String/Cons'.  1 | String/Cons = * diff --git a/tests/snapshots/run_file__readback_hvm1_main.bend.snap b/tests/snapshots/run_file__readback_hvm1_main.bend.snap index 25bda2fc2..3d189649c 100644 --- a/tests/snapshots/run_file__readback_hvm1_main.bend.snap +++ b/tests/snapshots/run_file__readback_hvm1_main.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/readback_hvm1_main.bend --- Errors: +During execution : In definition 'Main': Main definition can't be referenced inside the program. diff --git a/tests/snapshots/run_file__recursive_combinator_nested.bend.snap b/tests/snapshots/run_file__recursive_combinator_nested.bend.snap index e45fa3c3f..599376883 100644 --- a/tests/snapshots/run_file__recursive_combinator_nested.bend.snap +++ b/tests/snapshots/run_file__recursive_combinator_nested.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/recursive_combinator_nested.bend --- Errors: -In tests/golden_tests/run_file/recursive_combinator_nested.bend : +In tests/golden_tests/run_file/recursive_combinator_nested.bend : - expected: term - detected:  4 | _: a-1 diff --git a/tests/snapshots/run_file__str_inc.bend.snap b/tests/snapshots/run_file__str_inc.bend.snap index 265738757..edc1bc2fc 100644 --- a/tests/snapshots/run_file__str_inc.bend.snap +++ b/tests/snapshots/run_file__str_inc.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/str_inc.bend --- Errors: -In tests/golden_tests/run_file/str_inc.bend : +In tests/golden_tests/run_file/str_inc.bend : - expected: ')' - detected:  3 | (StrGo 0 str) = str diff --git a/tests/snapshots/run_file__str_inc_eta.bend.snap b/tests/snapshots/run_file__str_inc_eta.bend.snap index 89c3b993b..547ec8991 100644 --- a/tests/snapshots/run_file__str_inc_eta.bend.snap +++ b/tests/snapshots/run_file__str_inc_eta.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/str_inc_eta.bend --- Errors: -In tests/golden_tests/run_file/str_inc_eta.bend : +In tests/golden_tests/run_file/str_inc_eta.bend : - expected: ')' - detected:  3 | (StrGo 0 (head, tail)) = (head, tail) diff --git a/tests/snapshots/run_file__tagged_lam.bend.snap b/tests/snapshots/run_file__tagged_lam.bend.snap index 1f1db3205..11ade896f 100644 --- a/tests/snapshots/run_file__tagged_lam.bend.snap +++ b/tests/snapshots/run_file__tagged_lam.bend.snap @@ -3,7 +3,7 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/tagged_lam.bend --- Errors: -In tests/golden_tests/run_file/tagged_lam.bend : +In tests/golden_tests/run_file/tagged_lam.bend : - expected: term - detected: end of input  2 |   diff --git a/tests/snapshots/run_file__unbound_wrap.bend.snap b/tests/snapshots/run_file__unbound_wrap.bend.snap index a154a25f4..552967160 100644 --- a/tests/snapshots/run_file__unbound_wrap.bend.snap +++ b/tests/snapshots/run_file__unbound_wrap.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/unbound_wrap.bend --- Errors: +In tests/golden_tests/run_file/unbound_wrap.bend : In definition 'main': Reference to undefined function 'Maybe/wrap' diff --git a/tests/snapshots/run_file__unscoped_never_used.bend.snap b/tests/snapshots/run_file__unscoped_never_used.bend.snap index aeb93b145..4f5f367a1 100644 --- a/tests/snapshots/run_file__unscoped_never_used.bend.snap +++ b/tests/snapshots/run_file__unscoped_never_used.bend.snap @@ -3,5 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/unscoped_never_used.bend --- Errors: +In tests/golden_tests/run_file/unscoped_never_used.bend : In definition 'main': Unscoped variable from lambda 'λ$x' is never used. diff --git a/tests/snapshots/simplify_matches__wrong_fn_arity.bend.snap b/tests/snapshots/simplify_matches__wrong_fn_arity.bend.snap index 0420c05e2..f5559559a 100644 --- a/tests/snapshots/simplify_matches__wrong_fn_arity.bend.snap +++ b/tests/snapshots/simplify_matches__wrong_fn_arity.bend.snap @@ -3,6 +3,9 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/simplify_matches/wrong_fn_arity.bend --- Errors: +During execution : File has no 'main' definition. + +In tests/golden_tests/simplify_matches/wrong_fn_arity.bend : In definition 'Foo': Incorrect pattern matching rule arity. Expected 3 args, found 0. From 6365c0caeabba259644ea5b454396b6c2eb8356d Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Thu, 15 Aug 2024 21:09:44 -0300 Subject: [PATCH 19/24] Fix conflict between error expecting `String` getting `Diagnostics` --- tests/golden_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/golden_tests.rs b/tests/golden_tests.rs index 8374e64fe..618e55270 100644 --- a/tests/golden_tests.rs +++ b/tests/golden_tests.rs @@ -480,7 +480,7 @@ fn examples() -> Result<(), Diagnostics> { run_book(book, RunOpts::default(), compile_opts, diagnostics_cfg, None, "run-c")?.unwrap(); format!("{diags}{term}") } - Err(e) => e, + Err(e) => e.to_string(), }; let mut settings = insta::Settings::clone_current(); From 9b20e5172e26f8369e819bd78b88d0f904a15a57 Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Fri, 16 Aug 2024 12:55:32 -0300 Subject: [PATCH 20/24] Keep original source in generated definitions --- src/fun/mod.rs | 6 +++--- src/fun/transform/definition_merge.rs | 13 +++++++++---- src/fun/transform/encode_adts.rs | 8 ++++---- src/fun/transform/float_combinators.rs | 16 ++++++++-------- src/fun/transform/lift_local_defs.rs | 3 ++- 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/fun/mod.rs b/src/fun/mod.rs index abf0c4778..b88b5c246 100644 --- a/src/fun/mod.rs +++ b/src/fun/mod.rs @@ -1031,9 +1031,9 @@ impl Definition { Self { name, rules, source } } - pub fn new_gen(name: Name, rules: Vec, builtin: bool) -> Self { - let kind = if builtin { SourceKind::Builtin } else { SourceKind::Generated }; - let source = Source { file: None, span: None, kind }; + pub fn new_gen(name: Name, rules: Vec, source: Source) -> Self { + let kind = if source.is_builtin() { SourceKind::Builtin } else { SourceKind::Generated }; + let source = Source { kind, ..source }; Self { name, rules, source } } diff --git a/src/fun/transform/definition_merge.rs b/src/fun/transform/definition_merge.rs index a58befbea..8bfb48522 100644 --- a/src/fun/transform/definition_merge.rs +++ b/src/fun/transform/definition_merge.rs @@ -34,13 +34,18 @@ impl Book { // def1_$_def2_$_def3 let new_name = Name::new(equal_defs.iter().join(MERGE_SEPARATOR)); - // Builtin origin takes precedence - let builtin = equal_defs.iter().any(|nam| self.defs[nam].is_builtin()); - if equal_defs.len() > 1 { // Merging some defs // Add the merged def - let new_def = Definition::new_gen(new_name.clone(), vec![Rule { pats: vec![], body: term }], builtin); + + // The source of the generated definition will be based on the first one we get from `equal_defs`. + // In the future, we might want to change this to point to every source of every definition + // it's based on. + // This could be done by having SourceKind::Generated contain a Vec or Vec. + let any_def_name = equal_defs.iter().next().unwrap(); // we know we can unwrap since equal_defs.len() > 1 + let source = self.defs[any_def_name].source.clone(); + + let new_def = Definition::new_gen(new_name.clone(), vec![Rule { pats: vec![], body: term }], source); self.defs.insert(new_name.clone(), new_def); // Remove the old ones and write the map of old names to new ones. for name in equal_defs { diff --git a/src/fun/transform/encode_adts.rs b/src/fun/transform/encode_adts.rs index d937c0c16..9ef6c62cd 100644 --- a/src/fun/transform/encode_adts.rs +++ b/src/fun/transform/encode_adts.rs @@ -1,5 +1,5 @@ use crate::{ - fun::{Book, Definition, Name, Num, Pattern, Rule, Term}, + fun::{Book, Definition, Name, Num, Pattern, Rule, Source, Term}, AdtEncoding, }; @@ -18,7 +18,7 @@ impl Book { AdtEncoding::NumScott => { let tag = make_tag(adt_name == ctr_name, ctr_name); let body = encode_ctr_num_scott(fields.iter().map(|f| &f.nam), &tag); - let tag_def = make_tag_def(ctr_idx, &tag, adt.source.is_builtin()); + let tag_def = make_tag_def(ctr_idx, &tag, adt.source.clone()); tags.push((tag, tag_def)); body } @@ -65,7 +65,7 @@ fn encode_ctr_num_scott<'a>(ctr_args: impl DoubleEndedIterator Term::rfold_lams(term, ctr_args.cloned().map(Some)) } -fn make_tag_def(ctr_idx: usize, tag: &Name, builtin: bool) -> Definition { +fn make_tag_def(ctr_idx: usize, tag: &Name, source: Source) -> Definition { let tag_rule = vec![Rule { pats: vec![], body: Term::Num { val: Num::U24(ctr_idx as u32) } }]; - Definition::new_gen(tag.clone(), tag_rule, builtin) + Definition::new_gen(tag.clone(), tag_rule, source) } diff --git a/src/fun/transform/float_combinators.rs b/src/fun/transform/float_combinators.rs index 30bdb0134..f7870cc5e 100644 --- a/src/fun/transform/float_combinators.rs +++ b/src/fun/transform/float_combinators.rs @@ -1,5 +1,5 @@ use crate::{ - fun::{Book, Definition, Name, Pattern, Rule, Term}, + fun::{Book, Definition, Name, Pattern, Rule, Source, Term}, maybe_grow, multi_iterator, }; use std::collections::{BTreeMap, HashSet}; @@ -44,11 +44,11 @@ impl Book { } } - let builtin = def.is_builtin(); + let source = def.source.clone(); let body = &mut def.rule_mut().body; ctx.reset(); ctx.def_size = body.size(); - body.float_combinators(&mut ctx, def_name, builtin); + body.float_combinators(&mut ctx, def_name, source.clone()); } self.defs.extend(ctx.combinators.into_iter().map(|(nam, (_, def))| (nam, def))); @@ -84,11 +84,11 @@ impl<'b> FloatCombinatorsCtx<'b> { } impl Term { - fn float_combinators(&mut self, ctx: &mut FloatCombinatorsCtx, def_name: &Name, builtin: bool) { + fn float_combinators(&mut self, ctx: &mut FloatCombinatorsCtx, def_name: &Name, source: Source) { maybe_grow(|| { // Recursively float the grandchildren terms. for child in self.float_children_mut() { - child.float_combinators(ctx, def_name, builtin); + child.float_combinators(ctx, def_name, source.clone()); } let mut size = self.size(); @@ -104,14 +104,14 @@ impl Term { if child.is_combinator() && child_size > 0 && (!child_is_safe || extract_for_size) { ctx.def_size -= child_size; size -= child_size; - child.float(ctx, def_name, builtin, child_is_safe); + child.float(ctx, def_name, source.clone(), child_is_safe); } } }) } /// Inserts a new definition for the given term in the combinators map. - fn float(&mut self, ctx: &mut FloatCombinatorsCtx, def_name: &Name, builtin: bool, is_safe: bool) { + fn float(&mut self, ctx: &mut FloatCombinatorsCtx, def_name: &Name, source: Source, is_safe: bool) { let comb_name = Name::new(format!("{}{}{}", def_name, NAME_SEP, ctx.name_gen)); ctx.name_gen += 1; @@ -119,7 +119,7 @@ impl Term { let extracted_term = std::mem::replace(self, comb_ref); let rules = vec![Rule { body: extracted_term, pats: Vec::new() }]; - let rule = Definition::new_gen(comb_name.clone(), rules, builtin); + let rule = Definition::new_gen(comb_name.clone(), rules, source); ctx.combinators.insert(comb_name, (is_safe, rule)); } } diff --git a/src/fun/transform/lift_local_defs.rs b/src/fun/transform/lift_local_defs.rs index feb1e2beb..4cff00dd5 100644 --- a/src/fun/transform/lift_local_defs.rs +++ b/src/fun/transform/lift_local_defs.rs @@ -41,11 +41,12 @@ impl Term { defs.keys().filter(|name| name.starts_with(local_name.as_ref())).cloned().collect::>(); let (r#use, fvs, mut rules) = gen_use(inner_defs, &local_name, &def.name, nxt, std::mem::take(&mut def.rules)); + let source = std::mem::take(&mut def.source); *self = r#use; apply_closure(&mut rules, &fvs); - let new_def = Definition::new_gen(local_name.clone(), rules, false); + let new_def = Definition::new_gen(local_name.clone(), rules, source); defs.insert(local_name.clone(), new_def); } _ => { From bde36fc9380615ae3398a8c0f00098d07c454de7 Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Fri, 16 Aug 2024 13:11:03 -0300 Subject: [PATCH 21/24] Improve `definition_merge` comments --- src/fun/transform/definition_merge.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fun/transform/definition_merge.rs b/src/fun/transform/definition_merge.rs index 8bfb48522..54e9b8ef5 100644 --- a/src/fun/transform/definition_merge.rs +++ b/src/fun/transform/definition_merge.rs @@ -12,7 +12,7 @@ impl Book { /// Merges definitions that have the same structure into one definition. /// Expects variables to be linear. /// - /// Ignores origin of the rules when merging, + /// Some of the origins of the rules will be lost in this stage, /// Should not be preceded by passes that cares about the origins. pub fn merge_definitions(&mut self) { let defs: Vec<_> = self.defs.keys().cloned().collect(); @@ -36,7 +36,6 @@ impl Book { if equal_defs.len() > 1 { // Merging some defs - // Add the merged def // The source of the generated definition will be based on the first one we get from `equal_defs`. // In the future, we might want to change this to point to every source of every definition @@ -45,6 +44,7 @@ impl Book { let any_def_name = equal_defs.iter().next().unwrap(); // we know we can unwrap since equal_defs.len() > 1 let source = self.defs[any_def_name].source.clone(); + // Add the merged def let new_def = Definition::new_gen(new_name.clone(), vec![Rule { pats: vec![], body: term }], source); self.defs.insert(new_name.clone(), new_def); // Remove the old ones and write the map of old names to new ones. From 8e20371a7ed6bae53e012952924a55cc5a5612eb Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Fri, 16 Aug 2024 18:35:21 -0300 Subject: [PATCH 22/24] Change diagnostics printing so it doesn't include "During execution:" --- src/diagnostics.rs | 62 ++++++++++--------- .../cli__input_file_not_found.bend.snap | 1 - .../compile_file__cyclic_global_lam.bend.snap | 1 - .../compile_file__ref_to_main.bend.snap | 1 - .../compile_file__vicious_circles.bend.snap | 1 - .../compile_file_o_all__double_main.bend.snap | 1 - ...e_o_all__repeated_name_trucation.bend.snap | 1 - .../compile_file_o_all__self_ref.bend.snap | 2 - ...pile_file_o_no_all__bitonic_sort.bend.snap | 1 - ...pile_file_o_no_all__list_reverse.bend.snap | 1 - .../compile_file_o_no_all__sum_tree.bend.snap | 1 - .../compile_long__huge_tree.bend.snap | 1 - .../compile_long__long_str_file.bend.snap | 1 - .../import_system__import_main.bend.snap | 1 - .../import_system__import_main2.bend.snap | 1 - .../import_system__import_main3.bend.snap | 1 - ...ort_system__imports_alias_shadow.bend.snap | 1 - .../import_system__imports_conflict.bend.snap | 1 - ...m__imports_file_and_dir_conflict.bend.snap | 1 - .../import_system__imports_shadow.bend.snap | 1 - .../import_system__imports_shadow2.bend.snap | 1 - .../mutual_recursion__a_b_c.bend.snap | 1 - .../mutual_recursion__merged.bend.snap | 1 - .../mutual_recursion__multiple.bend.snap | 1 - .../mutual_recursion__odd_even.bend.snap | 1 - .../snapshots/readback_hvm__bad_net.bend.snap | 1 - .../readback_hvm__invalid_op2_op2.bend.snap | 1 - tests/snapshots/run_file__empty.bend.snap | 1 - tests/snapshots/run_file__exp.bend.snap | 2 - .../run_file__let_tup_readback.bend.snap | 2 - .../run_file__readback_hvm1_main.bend.snap | 1 - ...simplify_matches__wrong_fn_arity.bend.snap | 6 +- 32 files changed, 37 insertions(+), 64 deletions(-) diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 05b83287f..72b59e3ed 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -1,4 +1,3 @@ -use itertools::Itertools; use TSPL::ParseError; use crate::fun::{display::DisplayFn, Name, Source}; @@ -37,7 +36,7 @@ pub struct Diagnostic { pub source: Source, } -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum DiagnosticOrigin { /// An error when parsing source code. Parsing, @@ -204,42 +203,49 @@ impl Diagnostics { // In file B : // In compiled Inet Z : // {error} - // {...} + // + // Other diagnostics: + // In {...} // ``` // The problem is, diagnostics data is currently structured as a mapping from something like - // DiagnosticOrigin to (DiagnosticMessage, DiagnosticFile), and we would need something - // like a mapping from DiagnosticFile to DiagnosticOrigin to DiagnosticMessage in order + // DiagnosticOrigin to Vec<(DiagnosticMessage, DiagnosticFile)>, and we would need something + // like a mapping from DiagnosticFile to DiagnosticOrigin to Vec in order // to print it cleanly. We might want to change it later to have this structure, // but meanwhile, we do the transformations below to make the goal possible. - // Flatten Iter<(Origin, Vec)> into Iter<(Origin, Diagnostic)> + // Ignore diagnostics without the desired severity. let diagnostics = self .diagnostics .iter() - .flat_map(|(origin, diagnostics)| diagnostics.iter().map(move |diagnostic| (origin, diagnostic))); - // Remove diagnostics with unwanted Severity - let diagnostics = diagnostics.filter(|(_, diag)| diag.severity == severity); - // Group diagnostics by their file names - let file_groups = diagnostics.group_by(|diag| diag.1.source.file.as_ref()); - - // Now, we have a mapping from DiagnosticFile to (DiagnosticOrigin, DiagnosticMessage). - for (file, origins_and_diagnostics) in &file_groups { - // We don't have to check if the amount of diagnostics in this file is greater than 0, - // since we will only get a file if it was included in a diagnostic. - match &file { - Some(name) => writeln!(f, "\x1b[1mIn \x1b[4m{}\x1b[0m\x1b[1m :\x1b[0m", name)?, - None => writeln!(f, "\x1b[1mDuring execution :\x1b[0m")?, - }; - - // Group errors by their origin - let origin_groups = origins_and_diagnostics.group_by(|(origin, _)| *origin); + .map(|(origin, diags)| (origin, diags.iter().filter(|diag| diag.severity == severity))); + + // Produce the structure described above. + let groups = diagnostics.fold(BTreeMap::new(), |mut file_tree, (origin, diags)| { + for diag in diags { + let file_group_entry = file_tree.entry(&diag.source.file).or_insert_with(|| BTreeMap::new()); + let origin_group_entry = file_group_entry.entry(origin).or_insert_with(|| Vec::new()); + origin_group_entry.push(diag); + } + file_tree + }); + // Now, we have a mapping from DiagnosticFile to DiagnosticOrigin to Vec. + + // If the last file is `None`, it means we only have diagnostics with unknown source file. + // In this case, we won't print a special message for them. + let only_unknown_file_diagnostics = groups.keys().rev().next() == Some(&&None); + + // Reverse the group iterator so `None` files go last. + for (file, origin_to_diagnostics) in groups.iter().rev() { + if !only_unknown_file_diagnostics { + match &file { + Some(name) => writeln!(f, "\x1b[1mIn \x1b[4m{}\x1b[0m\x1b[1m :\x1b[0m", name)?, + None => writeln!(f, "\x1b[1mOther diagnostics:\x1b[0m")?, + }; + } let mut has_msg = false; - // Finally, we have our mapping of DiagnosticOrigin to DiagnosticMessage back. - for (origin, origins_and_diagnostics) in &origin_groups { - // We don't care about DiagnosticOrigins here, so remove them. - let mut diagnostics = origins_and_diagnostics.map(|(_, diag)| diag).peekable(); - + for (origin, diagnostics) in origin_to_diagnostics { + let mut diagnostics = diagnostics.iter().peekable(); if diagnostics.peek().is_some() { match origin { DiagnosticOrigin::Parsing => { diff --git a/tests/snapshots/cli__input_file_not_found.bend.snap b/tests/snapshots/cli__input_file_not_found.bend.snap index 1575a9b27..58ec93951 100644 --- a/tests/snapshots/cli__input_file_not_found.bend.snap +++ b/tests/snapshots/cli__input_file_not_found.bend.snap @@ -3,5 +3,4 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/cli/input_file_not_found.bend --- Errors: -During execution : The file 'tests/golden_tests/missing_dir/input_file_not_found.bend' was not found. diff --git a/tests/snapshots/compile_file__cyclic_global_lam.bend.snap b/tests/snapshots/compile_file__cyclic_global_lam.bend.snap index 2d5a1ed6c..7514d226f 100644 --- a/tests/snapshots/compile_file__cyclic_global_lam.bend.snap +++ b/tests/snapshots/compile_file__cyclic_global_lam.bend.snap @@ -3,6 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/cyclic_global_lam.bend --- Errors: -During execution : In compiled inet 'main': Found term that compiles into an inet with a vicious cycle diff --git a/tests/snapshots/compile_file__ref_to_main.bend.snap b/tests/snapshots/compile_file__ref_to_main.bend.snap index 440a4d94b..d0d1bfb62 100644 --- a/tests/snapshots/compile_file__ref_to_main.bend.snap +++ b/tests/snapshots/compile_file__ref_to_main.bend.snap @@ -3,6 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/ref_to_main.bend --- Errors: -During execution : In definition 'Foo': Main definition can't be referenced inside the program. diff --git a/tests/snapshots/compile_file__vicious_circles.bend.snap b/tests/snapshots/compile_file__vicious_circles.bend.snap index 924b0b4fb..4824d0655 100644 --- a/tests/snapshots/compile_file__vicious_circles.bend.snap +++ b/tests/snapshots/compile_file__vicious_circles.bend.snap @@ -3,7 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file/vicious_circles.bend --- Errors: -During execution : In compiled inet 'disconnected_self_lam': Found term that compiles into an inet with a vicious cycle In compiled inet 'dup_self': diff --git a/tests/snapshots/compile_file_o_all__double_main.bend.snap b/tests/snapshots/compile_file_o_all__double_main.bend.snap index 2abfc54ce..8d14ad81e 100644 --- a/tests/snapshots/compile_file_o_all__double_main.bend.snap +++ b/tests/snapshots/compile_file_o_all__double_main.bend.snap @@ -3,5 +3,4 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/double_main.bend --- Errors: -During execution : File has both 'main' and 'Main' definitions. diff --git a/tests/snapshots/compile_file_o_all__repeated_name_trucation.bend.snap b/tests/snapshots/compile_file_o_all__repeated_name_trucation.bend.snap index 014737cea..6265818d5 100644 --- a/tests/snapshots/compile_file_o_all__repeated_name_trucation.bend.snap +++ b/tests/snapshots/compile_file_o_all__repeated_name_trucation.bend.snap @@ -3,7 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/repeated_name_trucation.bend --- Warnings: -During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * long_name_that_truncates -> long_name_that_truncates diff --git a/tests/snapshots/compile_file_o_all__self_ref.bend.snap b/tests/snapshots/compile_file_o_all__self_ref.bend.snap index 75efad5e3..0ba6fcd03 100644 --- a/tests/snapshots/compile_file_o_all__self_ref.bend.snap +++ b/tests/snapshots/compile_file_o_all__self_ref.bend.snap @@ -3,7 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_all/self_ref.bend --- Warnings: -During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * Foo -> Foo @@ -33,6 +32,5 @@ To disable this check, use the "-Arecursion-cycle" compiler option. Errors: -During execution : During inlining: infinite reference cycle in `@Foo` diff --git a/tests/snapshots/compile_file_o_no_all__bitonic_sort.bend.snap b/tests/snapshots/compile_file_o_no_all__bitonic_sort.bend.snap index 195994ba7..187767b96 100644 --- a/tests/snapshots/compile_file_o_no_all__bitonic_sort.bend.snap +++ b/tests/snapshots/compile_file_o_no_all__bitonic_sort.bend.snap @@ -3,7 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_no_all/bitonic_sort.bend --- Errors: -During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * Down -> Flow -> Down * Warp -> Warp diff --git a/tests/snapshots/compile_file_o_no_all__list_reverse.bend.snap b/tests/snapshots/compile_file_o_no_all__list_reverse.bend.snap index 3625f7ff5..bc27b2d7b 100644 --- a/tests/snapshots/compile_file_o_no_all__list_reverse.bend.snap +++ b/tests/snapshots/compile_file_o_no_all__list_reverse.bend.snap @@ -3,7 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_no_all/list_reverse.bend --- Errors: -During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * concat -> concat * reverse -> reverse diff --git a/tests/snapshots/compile_file_o_no_all__sum_tree.bend.snap b/tests/snapshots/compile_file_o_no_all__sum_tree.bend.snap index 14b4c93ba..b7c2f6eb6 100644 --- a/tests/snapshots/compile_file_o_no_all__sum_tree.bend.snap +++ b/tests/snapshots/compile_file_o_no_all__sum_tree.bend.snap @@ -3,7 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_file_o_no_all/sum_tree.bend --- Errors: -During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * gen -> gen * sum -> sum diff --git a/tests/snapshots/compile_long__huge_tree.bend.snap b/tests/snapshots/compile_long__huge_tree.bend.snap index cee2bb6fd..ee6c230f5 100644 --- a/tests/snapshots/compile_long__huge_tree.bend.snap +++ b/tests/snapshots/compile_long__huge_tree.bend.snap @@ -3,6 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_long/huge_tree.bend --- Errors: -During execution : In definition 'main': Definition is too large for HVM C (size=120002, max size=4095). Please break it into smaller pieces. diff --git a/tests/snapshots/compile_long__long_str_file.bend.snap b/tests/snapshots/compile_long__long_str_file.bend.snap index 28ee629ac..b4e9f10d8 100644 --- a/tests/snapshots/compile_long__long_str_file.bend.snap +++ b/tests/snapshots/compile_long__long_str_file.bend.snap @@ -3,6 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/compile_long/long_str_file.bend --- Errors: -During execution : In definition 'main': Definition is too large for HVM C (size=1461028, max size=4095). Please break it into smaller pieces. diff --git a/tests/snapshots/import_system__import_main.bend.snap b/tests/snapshots/import_system__import_main.bend.snap index 074c947b3..c058f3a3d 100644 --- a/tests/snapshots/import_system__import_main.bend.snap +++ b/tests/snapshots/import_system__import_main.bend.snap @@ -3,5 +3,4 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/import_main.bend --- Errors: -During execution : Can not import the entry point of the program. diff --git a/tests/snapshots/import_system__import_main2.bend.snap b/tests/snapshots/import_system__import_main2.bend.snap index 5fbc9d195..698bbe8f3 100644 --- a/tests/snapshots/import_system__import_main2.bend.snap +++ b/tests/snapshots/import_system__import_main2.bend.snap @@ -3,5 +3,4 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/import_main2.bend --- Errors: -During execution : Can not import the entry point of the program. diff --git a/tests/snapshots/import_system__import_main3.bend.snap b/tests/snapshots/import_system__import_main3.bend.snap index 22138df46..f00d33137 100644 --- a/tests/snapshots/import_system__import_main3.bend.snap +++ b/tests/snapshots/import_system__import_main3.bend.snap @@ -3,5 +3,4 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/import_main3.bend --- Errors: -During execution : Can not import the entry point of the program. diff --git a/tests/snapshots/import_system__imports_alias_shadow.bend.snap b/tests/snapshots/import_system__imports_alias_shadow.bend.snap index ea8489fe6..1c6942786 100644 --- a/tests/snapshots/import_system__imports_alias_shadow.bend.snap +++ b/tests/snapshots/import_system__imports_alias_shadow.bend.snap @@ -3,5 +3,4 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/imports_alias_shadow.bend --- Errors: -During execution : The import 'lib/nums/two' shadows the imported name 'lib/nums/one' diff --git a/tests/snapshots/import_system__imports_conflict.bend.snap b/tests/snapshots/import_system__imports_conflict.bend.snap index 15d5f9dd5..f651bdd44 100644 --- a/tests/snapshots/import_system__imports_conflict.bend.snap +++ b/tests/snapshots/import_system__imports_conflict.bend.snap @@ -3,6 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/imports_conflict.bend --- Errors: -During execution : The imported definition 'lib/a/b/C' conflicts with the definition 'lib/a/b/C'. The imported constructor 'lib/a/b/C' conflicts with the definition 'lib/a/b/C'. diff --git a/tests/snapshots/import_system__imports_file_and_dir_conflict.bend.snap b/tests/snapshots/import_system__imports_file_and_dir_conflict.bend.snap index 3d9e0efda..4c28d7844 100644 --- a/tests/snapshots/import_system__imports_file_and_dir_conflict.bend.snap +++ b/tests/snapshots/import_system__imports_file_and_dir_conflict.bend.snap @@ -3,5 +3,4 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/imports_file_and_dir_conflict.bend --- Errors: -During execution : Both file 'lib/file_and_dir.bend' and folder 'lib/file_and_dir' contains the import 'w' diff --git a/tests/snapshots/import_system__imports_shadow.bend.snap b/tests/snapshots/import_system__imports_shadow.bend.snap index 34fee2cb7..284db8136 100644 --- a/tests/snapshots/import_system__imports_shadow.bend.snap +++ b/tests/snapshots/import_system__imports_shadow.bend.snap @@ -3,5 +3,4 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/imports_shadow.bend --- Errors: -During execution : The import 'lib/myFun/myFun' shadows the imported name 'lib/folder/myFun/myFun' diff --git a/tests/snapshots/import_system__imports_shadow2.bend.snap b/tests/snapshots/import_system__imports_shadow2.bend.snap index eb96db7fe..85e37d51d 100644 --- a/tests/snapshots/import_system__imports_shadow2.bend.snap +++ b/tests/snapshots/import_system__imports_shadow2.bend.snap @@ -3,5 +3,4 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/import_system/imports_shadow2.bend --- Errors: -During execution : The import 'lib/folder/myFun/myFun' shadows the imported name 'lib/myFun/myFun' diff --git a/tests/snapshots/mutual_recursion__a_b_c.bend.snap b/tests/snapshots/mutual_recursion__a_b_c.bend.snap index 7c3ef16fd..7a8d139a8 100644 --- a/tests/snapshots/mutual_recursion__a_b_c.bend.snap +++ b/tests/snapshots/mutual_recursion__a_b_c.bend.snap @@ -3,7 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/mutual_recursion/a_b_c.bend --- Errors: -During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * A -> B -> C -> A diff --git a/tests/snapshots/mutual_recursion__merged.bend.snap b/tests/snapshots/mutual_recursion__merged.bend.snap index cdcb0d945..739cfb0b9 100644 --- a/tests/snapshots/mutual_recursion__merged.bend.snap +++ b/tests/snapshots/mutual_recursion__merged.bend.snap @@ -3,7 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/mutual_recursion/merged.bend --- Errors: -During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * Rec -> X -> Rec * Rec -> Y -> Rec diff --git a/tests/snapshots/mutual_recursion__multiple.bend.snap b/tests/snapshots/mutual_recursion__multiple.bend.snap index 65a93e8a8..4605f2486 100644 --- a/tests/snapshots/mutual_recursion__multiple.bend.snap +++ b/tests/snapshots/mutual_recursion__multiple.bend.snap @@ -3,7 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/mutual_recursion/multiple.bend --- Errors: -During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * A -> B -> C -> A * H -> I -> H diff --git a/tests/snapshots/mutual_recursion__odd_even.bend.snap b/tests/snapshots/mutual_recursion__odd_even.bend.snap index 64a3610d2..4d8ea8667 100644 --- a/tests/snapshots/mutual_recursion__odd_even.bend.snap +++ b/tests/snapshots/mutual_recursion__odd_even.bend.snap @@ -3,7 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/mutual_recursion/odd_even.bend --- Errors: -During execution : The following functions contain recursive cycles incompatible with HVM's strict evaluation: * isEven -> isOdd -> isEven diff --git a/tests/snapshots/readback_hvm__bad_net.bend.snap b/tests/snapshots/readback_hvm__bad_net.bend.snap index 0bc29607d..af03cc7cc 100644 --- a/tests/snapshots/readback_hvm__bad_net.bend.snap +++ b/tests/snapshots/readback_hvm__bad_net.bend.snap @@ -3,7 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/readback_hvm/bad_net.bend --- Warnings: -During execution : During readback: Unable to interpret the HVM result as a valid Bend term. (Reached Root) diff --git a/tests/snapshots/readback_hvm__invalid_op2_op2.bend.snap b/tests/snapshots/readback_hvm__invalid_op2_op2.bend.snap index 6432cf894..930777230 100644 --- a/tests/snapshots/readback_hvm__invalid_op2_op2.bend.snap +++ b/tests/snapshots/readback_hvm__invalid_op2_op2.bend.snap @@ -3,7 +3,6 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/readback_hvm/invalid_op2_op2.bend --- Warnings: -During execution : During readback: Encountered an invalid numeric operation. (3 occurrences) diff --git a/tests/snapshots/run_file__empty.bend.snap b/tests/snapshots/run_file__empty.bend.snap index 7b6c2c060..ae0322092 100644 --- a/tests/snapshots/run_file__empty.bend.snap +++ b/tests/snapshots/run_file__empty.bend.snap @@ -3,5 +3,4 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/empty.bend --- Errors: -During execution : File has no 'main' definition. diff --git a/tests/snapshots/run_file__exp.bend.snap b/tests/snapshots/run_file__exp.bend.snap index bb4d68a7f..ca80eb038 100644 --- a/tests/snapshots/run_file__exp.bend.snap +++ b/tests/snapshots/run_file__exp.bend.snap @@ -4,7 +4,6 @@ input_file: tests/golden_tests/run_file/exp.bend --- NumScott: Warnings: -During execution : During readback: Unable to interpret the HVM result as a valid Bend term. (Reached Root) @@ -12,7 +11,6 @@ NumScott: Scott: Warnings: -During execution : During readback: Unable to interpret the HVM result as a valid Bend term. (Reached Root) diff --git a/tests/snapshots/run_file__let_tup_readback.bend.snap b/tests/snapshots/run_file__let_tup_readback.bend.snap index df9e7629b..662ee8a9e 100644 --- a/tests/snapshots/run_file__let_tup_readback.bend.snap +++ b/tests/snapshots/run_file__let_tup_readback.bend.snap @@ -4,7 +4,6 @@ input_file: tests/golden_tests/run_file/let_tup_readback.bend --- NumScott: Warnings: -During execution : During readback: Unable to interpret the HVM result as a valid Bend term. (Reached Root) @@ -12,7 +11,6 @@ NumScott: Scott: Warnings: -During execution : During readback: Unable to interpret the HVM result as a valid Bend term. (Reached Root) diff --git a/tests/snapshots/run_file__readback_hvm1_main.bend.snap b/tests/snapshots/run_file__readback_hvm1_main.bend.snap index 3d189649c..25bda2fc2 100644 --- a/tests/snapshots/run_file__readback_hvm1_main.bend.snap +++ b/tests/snapshots/run_file__readback_hvm1_main.bend.snap @@ -3,6 +3,5 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/run_file/readback_hvm1_main.bend --- Errors: -During execution : In definition 'Main': Main definition can't be referenced inside the program. diff --git a/tests/snapshots/simplify_matches__wrong_fn_arity.bend.snap b/tests/snapshots/simplify_matches__wrong_fn_arity.bend.snap index f5559559a..d75933f7f 100644 --- a/tests/snapshots/simplify_matches__wrong_fn_arity.bend.snap +++ b/tests/snapshots/simplify_matches__wrong_fn_arity.bend.snap @@ -3,9 +3,9 @@ source: tests/golden_tests.rs input_file: tests/golden_tests/simplify_matches/wrong_fn_arity.bend --- Errors: -During execution : -File has no 'main' definition. - In tests/golden_tests/simplify_matches/wrong_fn_arity.bend : In definition 'Foo': Incorrect pattern matching rule arity. Expected 3 args, found 0. + +Other diagnostics: +File has no 'main' definition. From 98625333da597cf6b3b3c5f36cf11eb50e7ea48d Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Fri, 16 Aug 2024 18:49:35 -0300 Subject: [PATCH 23/24] Fix clippy warning --- src/diagnostics.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 72b59e3ed..c8264ae37 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -220,19 +220,23 @@ impl Diagnostics { .map(|(origin, diags)| (origin, diags.iter().filter(|diag| diag.severity == severity))); // Produce the structure described above. - let groups = diagnostics.fold(BTreeMap::new(), |mut file_tree, (origin, diags)| { - for diag in diags { - let file_group_entry = file_tree.entry(&diag.source.file).or_insert_with(|| BTreeMap::new()); - let origin_group_entry = file_group_entry.entry(origin).or_insert_with(|| Vec::new()); - origin_group_entry.push(diag); - } - file_tree - }); + let groups: BTreeMap<&Option, BTreeMap<&DiagnosticOrigin, Vec<&Diagnostic>>> = diagnostics + .fold(BTreeMap::new(), |mut file_tree, (origin, diags)| { + for diag in diags { + // We need to allow this Clippy warning due to `Name` in `DiagnosticOrigin::Function`. + // We know how it works, so it shouldn't be a problem. + #[allow(clippy::mutable_key_type)] + let file_group_entry = file_tree.entry(&diag.source.file).or_default(); + let origin_group_entry = file_group_entry.entry(origin).or_default(); + origin_group_entry.push(diag); + } + file_tree + }); // Now, we have a mapping from DiagnosticFile to DiagnosticOrigin to Vec. // If the last file is `None`, it means we only have diagnostics with unknown source file. // In this case, we won't print a special message for them. - let only_unknown_file_diagnostics = groups.keys().rev().next() == Some(&&None); + let only_unknown_file_diagnostics = groups.keys().next_back() == Some(&&None); // Reverse the group iterator so `None` files go last. for (file, origin_to_diagnostics) in groups.iter().rev() { From e1ba43d7558b038d21fe933ecdc7f0089fad5bfa Mon Sep 17 00:00:00 2001 From: Eduardo Sandalo Porto Date: Mon, 19 Aug 2024 09:08:33 -0300 Subject: [PATCH 24/24] Add changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6799e5317..6a87cc5b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project does not currently adhere to a particular versioning scheme. - Change branches to support ending with ask statements. ([#629][gh-629]) - Improve hexadecimal and binary floating numbers. ([#648][gh-648]) - Change IO functions to return Result. ([#657][gh-657]) +- Revamp the diagnostics system and parser to show more error and warning messages ([#673][gh-673]) ## [0.2.36] - 2024-07-04 @@ -420,4 +421,5 @@ and this project does not currently adhere to a particular versioning scheme. [gh-648]: https://github.com/HigherOrderCO/Bend/issues/648 [gh-657]: https://github.com/HigherOrderCO/Bend/issues/657 [gh-659]: https://github.com/HigherOrderCO/Bend/pull/659 +[gh-673]: https://github.com/HigherOrderCO/Bend/pull/673 [Unreleased]: https://github.com/HigherOrderCO/Bend/compare/0.2.36...HEAD