mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
Add granular errors regarding numeric literal parsing
This commit is contained in:
parent
f55e767035
commit
17c5fe0bff
4 changed files with 197 additions and 16 deletions
|
@ -152,7 +152,9 @@ fn chomp_number_base<'a>(
|
|||
},
|
||||
new,
|
||||
)),
|
||||
Some(NumWidth::Float(_)) => Err((Progress::MadeProgress, ENumber::End, state)),
|
||||
Some(NumWidth::Float(_)) => {
|
||||
Err((Progress::MadeProgress, ENumber::IntHasFloatSuffix, state))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +203,9 @@ fn chomp_number_dec<'a>(
|
|||
NumLiteral::Int(string, NumericBound::Exact(iw)),
|
||||
new,
|
||||
)),
|
||||
(true, Some(NumWidth::Int(_))) => Err((Progress::MadeProgress, ENumber::End, state)),
|
||||
(true, Some(NumWidth::Int(_))) => {
|
||||
Err((Progress::MadeProgress, ENumber::FloatHasIntSuffix, state))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,6 +286,20 @@ fn chomp_number<'a>(
|
|||
return Err((Progress::NoProgress, ENumber::End, state));
|
||||
}
|
||||
|
||||
if bytes
|
||||
.get(0)
|
||||
.copied()
|
||||
.unwrap_or_default()
|
||||
.is_ascii_alphabetic()
|
||||
{
|
||||
// The user likely mistyped a literal suffix type here.
|
||||
return Err((
|
||||
Progress::MadeProgress,
|
||||
ENumber::LiteralSuffix,
|
||||
state.advance(start_bytes_len - bytes.len()),
|
||||
));
|
||||
}
|
||||
|
||||
return Err((Progress::MadeProgress, ENumber::End, state));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -338,6 +338,9 @@ pub enum EExpr<'a> {
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum ENumber {
|
||||
End,
|
||||
LiteralSuffix,
|
||||
IntHasFloatSuffix,
|
||||
FloatHasIntSuffix,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
|
|
@ -522,6 +522,15 @@ fn to_expr_report<'a>(
|
|||
&EExpr::Number(ENumber::End, pos) => {
|
||||
to_malformed_number_literal_report(alloc, lines, filename, pos)
|
||||
}
|
||||
&EExpr::Number(ENumber::LiteralSuffix, pos) => {
|
||||
to_number_literal_with_bad_suffix_report(alloc, lines, filename, pos)
|
||||
}
|
||||
&EExpr::Number(ENumber::IntHasFloatSuffix, pos) => {
|
||||
to_number_literal_mismatch_suffix(alloc, lines, filename, pos, "an integer", "a float")
|
||||
}
|
||||
&EExpr::Number(ENumber::FloatHasIntSuffix, pos) => {
|
||||
to_number_literal_mismatch_suffix(alloc, lines, filename, pos, "a float", "an integer")
|
||||
}
|
||||
|
||||
_ => todo!("unhandled parse error: {:?}", parse_problem),
|
||||
}
|
||||
|
@ -1561,6 +1570,15 @@ fn to_pattern_report<'a>(
|
|||
&EPattern::NumLiteral(ENumber::End, pos) => {
|
||||
to_malformed_number_literal_report(alloc, lines, filename, pos)
|
||||
}
|
||||
&EPattern::NumLiteral(ENumber::LiteralSuffix, pos) => {
|
||||
to_number_literal_with_bad_suffix_report(alloc, lines, filename, pos)
|
||||
}
|
||||
&EPattern::NumLiteral(ENumber::IntHasFloatSuffix, pos) => {
|
||||
to_number_literal_mismatch_suffix(alloc, lines, filename, pos, "an integer", "a float")
|
||||
}
|
||||
&EPattern::NumLiteral(ENumber::FloatHasIntSuffix, pos) => {
|
||||
to_number_literal_mismatch_suffix(alloc, lines, filename, pos, "a float", "an integer")
|
||||
}
|
||||
_ => todo!("unhandled parse error: {:?}", parse_problem),
|
||||
}
|
||||
}
|
||||
|
@ -1976,6 +1994,57 @@ fn to_malformed_number_literal_report<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn to_number_literal_with_bad_suffix_report<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
lines: &LineInfo,
|
||||
filename: PathBuf,
|
||||
start: Position,
|
||||
) -> Report<'a> {
|
||||
let surroundings = Region::new(start, start);
|
||||
let region = LineColumnRegion::from_pos(lines.convert_pos(start));
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.reflow(r"It looks like you are trying to use type suffix on this number literal, but it's not one that I recognize:"),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "INVALID NUMBER LITERAL SUFFIX".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_number_literal_mismatch_suffix<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
lines: &LineInfo,
|
||||
filename: PathBuf,
|
||||
start: Position,
|
||||
literal_kind: &'static str,
|
||||
suffix_kind: &'static str,
|
||||
) -> Report<'a> {
|
||||
let surroundings = Region::new(start, start);
|
||||
let region = LineColumnRegion::from_pos(lines.convert_pos(start));
|
||||
|
||||
let doc = alloc.stack(vec![
|
||||
alloc.concat(vec![
|
||||
alloc.text(r"This number literal is "),
|
||||
alloc.text(literal_kind),
|
||||
alloc.text(", but its suffix says it's "),
|
||||
alloc.text(suffix_kind),
|
||||
]),
|
||||
alloc.region_with_subregion(lines.convert_region(surroundings), region),
|
||||
]);
|
||||
|
||||
Report {
|
||||
filename,
|
||||
doc,
|
||||
title: "NUMBER LITERAL CONFLICTS WITH SUFFIX".to_string(),
|
||||
severity: Severity::RuntimeError,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_type_report<'a>(
|
||||
alloc: &'a RocDocAllocator<'a>,
|
||||
lines: &LineInfo,
|
||||
|
|
|
@ -1730,9 +1730,10 @@ mod test_reporting {
|
|||
),
|
||||
indoc!(
|
||||
r#"
|
||||
── INVALID NUMBER LITERAL ──────────────────────────────────────────────────────
|
||||
── INVALID NUMBER LITERAL SUFFIX ───────────────────────────────────────────────
|
||||
|
||||
This number literal is malformed:
|
||||
It looks like you are trying to use type suffix on this number
|
||||
literal, but it's not one that I recognize:
|
||||
|
||||
2│ 100A -> 3
|
||||
^
|
||||
|
@ -1753,9 +1754,10 @@ mod test_reporting {
|
|||
),
|
||||
indoc!(
|
||||
r#"
|
||||
── INVALID NUMBER LITERAL ──────────────────────────────────────────────────────
|
||||
── INVALID NUMBER LITERAL SUFFIX ───────────────────────────────────────────────
|
||||
|
||||
This number literal is malformed:
|
||||
It looks like you are trying to use type suffix on this number
|
||||
literal, but it's not one that I recognize:
|
||||
|
||||
2│ 2.X -> 3
|
||||
^
|
||||
|
@ -1776,9 +1778,10 @@ mod test_reporting {
|
|||
),
|
||||
indoc!(
|
||||
r#"
|
||||
── INVALID NUMBER LITERAL ──────────────────────────────────────────────────────
|
||||
── INVALID NUMBER LITERAL SUFFIX ───────────────────────────────────────────────
|
||||
|
||||
This number literal is malformed:
|
||||
It looks like you are trying to use type suffix on this number
|
||||
literal, but it's not one that I recognize:
|
||||
|
||||
2│ 0xZ -> 3
|
||||
^
|
||||
|
@ -3533,9 +3536,10 @@ mod test_reporting {
|
|||
),
|
||||
indoc!(
|
||||
r#"
|
||||
── INVALID NUMBER LITERAL ──────────────────────────────────────────────────────
|
||||
── INVALID NUMBER LITERAL SUFFIX ───────────────────────────────────────────────
|
||||
|
||||
This number literal is malformed:
|
||||
It looks like you are trying to use type suffix on this number
|
||||
literal, but it's not one that I recognize:
|
||||
|
||||
1│ dec = 100A
|
||||
^
|
||||
|
@ -3614,9 +3618,10 @@ mod test_reporting {
|
|||
),
|
||||
indoc!(
|
||||
r#"
|
||||
── INVALID NUMBER LITERAL ──────────────────────────────────────────────────────
|
||||
── INVALID NUMBER LITERAL SUFFIX ───────────────────────────────────────────────
|
||||
|
||||
This number literal is malformed:
|
||||
It looks like you are trying to use type suffix on this number
|
||||
literal, but it's not one that I recognize:
|
||||
|
||||
1│ x = 3.0A
|
||||
^
|
||||
|
@ -7316,4 +7321,90 @@ I need all branches in an `if` to have the same type!
|
|||
1, "f32", mismatched_suffix_f32
|
||||
1, "f64", mismatched_suffix_f64
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bad_numeric_literal_suffix() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
1u256
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
── INVALID NUMBER LITERAL SUFFIX ───────────────────────────────────────────────
|
||||
|
||||
It looks like you are trying to use type suffix on this number
|
||||
literal, but it's not one that I recognize:
|
||||
|
||||
1│ 1u256
|
||||
^
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn numer_literal_multi_suffix() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
1u8u8
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
── INVALID NUMBER LITERAL SUFFIX ───────────────────────────────────────────────
|
||||
|
||||
It looks like you are trying to use type suffix on this number
|
||||
literal, but it's not one that I recognize:
|
||||
|
||||
1│ 1u8u8
|
||||
^
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn int_literal_has_float_suffix() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
0b1f32
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
── NUMBER LITERAL CONFLICTS WITH SUFFIX ────────────────────────────────────────
|
||||
|
||||
This number literal is an integer, but its suffix says it's a float
|
||||
|
||||
1│ 0b1f32
|
||||
^
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float_literal_has_int_suffix() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
1.0u8
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
── NUMBER LITERAL CONFLICTS WITH SUFFIX ────────────────────────────────────────
|
||||
|
||||
This number literal is a float, but its suffix says it's an integer
|
||||
|
||||
1│ 1.0u8
|
||||
^
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue