Merge branch 'trunk' into format-annotations

This commit is contained in:
Folkert de Vries 2020-07-09 18:10:20 +02:00 committed by GitHub
commit 3a6edd6594
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 7 deletions

View file

@ -121,8 +121,13 @@ pub fn finish_parsing_float(raw: &str) -> Result<f64, (&str, FloatErrorKind)> {
} }
} }
/// Integer parsing code taken from the rust stdlib, /// Integer parsing code taken from the rust libcore,
/// pulled in so we can give custom error messages /// pulled in so we can give custom error messages
///
/// The Rust Project is dual-licensed under Apache 2.0 and MIT terms.
/// As roc is Apache licensed, we use this rust code under the apache 2.0 license
///
/// Thanks to the rust-lang project and its contributors
trait FromStrRadixHelper: PartialOrd + Copy { trait FromStrRadixHelper: PartialOrd + Copy {
fn min_value() -> Self; fn min_value() -> Self;

View file

@ -68,6 +68,7 @@ pub enum IntErrorKind {
/// Value being parsed is empty. /// Value being parsed is empty.
/// ///
/// Among other causes, this variant will be constructed when parsing an empty string. /// Among other causes, this variant will be constructed when parsing an empty string.
/// In roc, this can happen with non-base-10 literals, e.g. `0x` or `0b` without any digits
Empty, Empty,
/// Contains an invalid digit. /// Contains an invalid digit.
/// ///

View file

@ -430,12 +430,22 @@ fn pretty_runtime_error<'b>(
hint, hint,
]) ])
} }
RuntimeError::InvalidInt(IntErrorKind::Empty, _base, _region, _raw_str) => { RuntimeError::InvalidInt(error @ IntErrorKind::InvalidDigit, base, region, _raw_str)
unreachable!("would never parse an empty int literal") | RuntimeError::InvalidInt(error @ IntErrorKind::Empty, base, region, _raw_str) => {
}
RuntimeError::InvalidInt(IntErrorKind::InvalidDigit, base, region, _raw_str) => {
use roc_parse::ast::Base::*; use roc_parse::ast::Base::*;
let (problem, contains) = if let IntErrorKind::InvalidDigit = error {
(
"an invalid digit",
alloc.reflow(" can only contain the digits "),
)
} else {
(
"no digits",
alloc.reflow(" must contain at least one of the digits "),
)
};
let name = match base { let name = match base {
Decimal => "integer", Decimal => "integer",
Octal => "octal integer", Octal => "octal integer",
@ -465,12 +475,14 @@ fn pretty_runtime_error<'b>(
alloc.concat(vec![ alloc.concat(vec![
alloc.reflow("This "), alloc.reflow("This "),
alloc.text(name), alloc.text(name),
alloc.reflow(" literal contains an invalid digit:"), alloc.reflow(" literal contains "),
alloc.text(problem),
alloc.text(":"),
]), ]),
alloc.region(region), alloc.region(region),
alloc.concat(vec![ alloc.concat(vec![
alloc.text(plurals), alloc.text(plurals),
alloc.reflow(" can only contain the digits "), contains,
alloc.text(charset), alloc.text(charset),
alloc.text("."), alloc.text("."),
]), ]),

View file

@ -3310,6 +3310,64 @@ mod test_reporting {
) )
} }
#[test]
fn integer_empty() {
report_problem_as(
indoc!(
r#"
dec = 20
hex = 0x
oct = 0o
bin = 0b
dec + hex + oct + bin
"#
),
indoc!(
r#"
-- SYNTAX PROBLEM --------------------------------------------------------------
This hex integer literal contains no digits:
3 hex = 0x
^^
Hexadecimal (base-16) integer literals must contain at least one of
the digits 0-9, a-f and A-F.
Hint: Learn more about number literals at TODO
-- SYNTAX PROBLEM --------------------------------------------------------------
This octal integer literal contains no digits:
5 oct = 0o
^^
Octal (base-8) integer literals must contain at least one of the
digits 0-7.
Hint: Learn more about number literals at TODO
-- SYNTAX PROBLEM --------------------------------------------------------------
This binary integer literal contains no digits:
7 bin = 0b
^^
Binary (base-2) integer literals must contain at least one of the
digits 0 and 1.
Hint: Learn more about number literals at TODO
"#
),
)
}
#[test] #[test]
fn float_malformed() { fn float_malformed() {
report_problem_as( report_problem_as(