mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +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,
|
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)),
|
NumLiteral::Int(string, NumericBound::Exact(iw)),
|
||||||
new,
|
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));
|
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));
|
return Err((Progress::MadeProgress, ENumber::End, state));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,6 +338,9 @@ pub enum EExpr<'a> {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum ENumber {
|
pub enum ENumber {
|
||||||
End,
|
End,
|
||||||
|
LiteralSuffix,
|
||||||
|
IntHasFloatSuffix,
|
||||||
|
FloatHasIntSuffix,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
|
|
@ -522,6 +522,15 @@ fn to_expr_report<'a>(
|
||||||
&EExpr::Number(ENumber::End, pos) => {
|
&EExpr::Number(ENumber::End, pos) => {
|
||||||
to_malformed_number_literal_report(alloc, lines, filename, 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),
|
_ => todo!("unhandled parse error: {:?}", parse_problem),
|
||||||
}
|
}
|
||||||
|
@ -1561,6 +1570,15 @@ fn to_pattern_report<'a>(
|
||||||
&EPattern::NumLiteral(ENumber::End, pos) => {
|
&EPattern::NumLiteral(ENumber::End, pos) => {
|
||||||
to_malformed_number_literal_report(alloc, lines, filename, 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),
|
_ => 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>(
|
fn to_type_report<'a>(
|
||||||
alloc: &'a RocDocAllocator<'a>,
|
alloc: &'a RocDocAllocator<'a>,
|
||||||
lines: &LineInfo,
|
lines: &LineInfo,
|
||||||
|
|
|
@ -1730,9 +1730,10 @@ mod test_reporting {
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
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
|
2│ 100A -> 3
|
||||||
^
|
^
|
||||||
|
@ -1753,9 +1754,10 @@ mod test_reporting {
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
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
|
2│ 2.X -> 3
|
||||||
^
|
^
|
||||||
|
@ -1776,9 +1778,10 @@ mod test_reporting {
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
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
|
2│ 0xZ -> 3
|
||||||
^
|
^
|
||||||
|
@ -3533,9 +3536,10 @@ mod test_reporting {
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
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
|
1│ dec = 100A
|
||||||
^
|
^
|
||||||
|
@ -3614,9 +3618,10 @@ mod test_reporting {
|
||||||
),
|
),
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
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
|
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, "f32", mismatched_suffix_f32
|
||||||
1, "f64", mismatched_suffix_f64
|
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