mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Merge remote-tracking branch 'origin/trunk' into low-level-ops
This commit is contained in:
commit
1cd49689c2
29 changed files with 1630 additions and 440 deletions
|
@ -1,6 +1,7 @@
|
|||
use roc_collections::all::MutSet;
|
||||
use roc_problem::can::PrecedenceProblem::BothNonAssociative;
|
||||
use roc_problem::can::{Problem, RuntimeError};
|
||||
use roc_problem::can::{FloatErrorKind, IntErrorKind, Problem, RuntimeError};
|
||||
use roc_region::all::Region;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::report::{Annotation, Report, RocDocAllocator, RocDocBuilder};
|
||||
|
@ -238,6 +239,29 @@ pub fn can_problem<'b>(
|
|||
alloc.reflow(" definitions from this tag union type."),
|
||||
]),
|
||||
]),
|
||||
Problem::SignatureDefMismatch {
|
||||
ref annotation_pattern,
|
||||
ref def_pattern,
|
||||
} => alloc.stack(vec![
|
||||
alloc.reflow("This annotation does not match the definition immediately following it:"),
|
||||
alloc.region(Region::span_across(annotation_pattern, def_pattern)),
|
||||
alloc.reflow("Is it a typo? If not, put either a newline or comment between them."),
|
||||
]),
|
||||
Problem::InvalidAliasRigid { alias_name, region } => alloc.stack(vec![
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("This pattern in the definition of "),
|
||||
alloc.symbol_unqualified(alias_name),
|
||||
alloc.reflow(" is not what I expect:"),
|
||||
]),
|
||||
alloc.region(region),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("Only type variables like "),
|
||||
alloc.type_variable("a".into()),
|
||||
alloc.reflow(" or "),
|
||||
alloc.type_variable("value".into()),
|
||||
alloc.reflow(" can occur in this position."),
|
||||
]),
|
||||
]),
|
||||
Problem::RuntimeError(runtime_error) => pretty_runtime_error(alloc, runtime_error),
|
||||
};
|
||||
|
||||
|
@ -274,13 +298,13 @@ fn pretty_runtime_error<'b>(
|
|||
RuntimeError::LookupNotInScope(loc_name, options) => {
|
||||
not_found(alloc, loc_name.region, &loc_name.value, "value", options)
|
||||
}
|
||||
RuntimeError::CircularDef(mut idents, regions) => {
|
||||
let first = idents.remove(0);
|
||||
RuntimeError::CircularDef(mut symbols, regions) => {
|
||||
let first = symbols.remove(0);
|
||||
|
||||
if idents.is_empty() {
|
||||
if symbols.is_empty() {
|
||||
alloc
|
||||
.reflow("The ")
|
||||
.append(alloc.ident(first.value))
|
||||
.append(alloc.symbol_unqualified(first))
|
||||
.append(alloc.reflow(
|
||||
" value is defined directly in terms of itself, causing an infinite loop.",
|
||||
))
|
||||
|
@ -290,62 +314,193 @@ fn pretty_runtime_error<'b>(
|
|||
alloc.stack(vec![
|
||||
alloc
|
||||
.reflow("The ")
|
||||
.append(alloc.ident(first.value.clone()))
|
||||
.append(alloc.symbol_unqualified(first))
|
||||
.append(
|
||||
alloc.reflow(" definition is causing a very tricky infinite loop:"),
|
||||
),
|
||||
alloc.region(regions[0].0),
|
||||
alloc
|
||||
.reflow("The ")
|
||||
.append(alloc.ident(first.value.clone()))
|
||||
.append(alloc.symbol_unqualified(first))
|
||||
.append(alloc.reflow(
|
||||
" value depends on itself through the following chain of definitions:",
|
||||
)),
|
||||
crate::report::cycle(
|
||||
alloc,
|
||||
4,
|
||||
alloc.ident(first.value),
|
||||
idents
|
||||
alloc.symbol_unqualified(first),
|
||||
symbols
|
||||
.into_iter()
|
||||
.map(|ident| alloc.ident(ident.value))
|
||||
.map(|s| alloc.symbol_unqualified(s))
|
||||
.collect::<Vec<_>>(),
|
||||
),
|
||||
// TODO hint?
|
||||
])
|
||||
}
|
||||
}
|
||||
other => {
|
||||
// // Example: (5 = 1 + 2) is an unsupported pattern in an assignment; Int patterns aren't allowed in assignments!
|
||||
// UnsupportedPattern(Region),
|
||||
// UnrecognizedFunctionName(Located<InlinableString>),
|
||||
// SymbolNotExposed {
|
||||
// module_name: InlinableString,
|
||||
// ident: InlinableString,
|
||||
// region: Region,
|
||||
// },
|
||||
// ModuleNotImported {
|
||||
// module_name: InlinableString,
|
||||
// ident: InlinableString,
|
||||
// region: Region,
|
||||
// },
|
||||
// InvalidPrecedence(PrecedenceProblem, Region),
|
||||
// MalformedIdentifier(Box<str>, Region),
|
||||
// MalformedClosure(Region),
|
||||
// FloatOutsideRange(Box<str>),
|
||||
// IntOutsideRange(Box<str>),
|
||||
// InvalidHex(std::num::ParseIntError, Box<str>),
|
||||
// InvalidOctal(std::num::ParseIntError, Box<str>),
|
||||
// InvalidBinary(std::num::ParseIntError, Box<str>),
|
||||
// QualifiedPatternIdent(InlinableString),
|
||||
// CircularDef(
|
||||
// Vec<Located<Ident>>,
|
||||
// Vec<(Region /* pattern */, Region /* expr */)>,
|
||||
// ),
|
||||
//
|
||||
// /// When the author specifies a type annotation but no implementation
|
||||
// NoImplementation,
|
||||
todo!("TODO implement run time error reporting for {:?}", other)
|
||||
RuntimeError::MalformedPattern(problem, region) => {
|
||||
use roc_parse::ast::Base;
|
||||
use roc_problem::can::MalformedPatternProblem::*;
|
||||
|
||||
let name = match problem {
|
||||
MalformedInt => " integer ",
|
||||
MalformedFloat => " float ",
|
||||
MalformedBase(Base::Hex) => " hex integer ",
|
||||
MalformedBase(Base::Binary) => " binary integer ",
|
||||
MalformedBase(Base::Octal) => " octal integer ",
|
||||
MalformedBase(Base::Decimal) => " integer ",
|
||||
Unknown => " ",
|
||||
QualifiedIdentifier => " qualified ",
|
||||
};
|
||||
|
||||
let hint = match problem {
|
||||
MalformedInt | MalformedFloat | MalformedBase(_) => alloc
|
||||
.hint()
|
||||
.append(alloc.reflow("Learn more about number literals at TODO")),
|
||||
Unknown => alloc.nil(),
|
||||
QualifiedIdentifier => alloc.hint().append(
|
||||
alloc.reflow("In patterns, only private and global tags can be qualified"),
|
||||
),
|
||||
};
|
||||
|
||||
alloc.stack(vec![
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("This"),
|
||||
alloc.text(name),
|
||||
alloc.reflow("pattern is malformed:"),
|
||||
]),
|
||||
alloc.region(region),
|
||||
hint,
|
||||
])
|
||||
}
|
||||
RuntimeError::UnsupportedPattern(_) => {
|
||||
todo!("unsupported patterns are currently not parsed!")
|
||||
}
|
||||
RuntimeError::ValueNotExposed { .. } => todo!("value not exposed"),
|
||||
RuntimeError::ModuleNotImported { .. } => todo!("module not imported"),
|
||||
RuntimeError::InvalidPrecedence(_, _) => {
|
||||
// do nothing, reported with PrecedenceProblem
|
||||
unreachable!()
|
||||
}
|
||||
RuntimeError::MalformedIdentifier(_, _) => {
|
||||
todo!("malformed identifier, currently gives a parse error and thus is unreachable")
|
||||
}
|
||||
RuntimeError::MalformedClosure(_) => todo!(""),
|
||||
RuntimeError::InvalidFloat(sign @ FloatErrorKind::PositiveInfinity, region, _raw_str)
|
||||
| RuntimeError::InvalidFloat(sign @ FloatErrorKind::NegativeInfinity, region, _raw_str) => {
|
||||
let hint = alloc
|
||||
.hint()
|
||||
.append(alloc.reflow("Learn more about number literals at TODO"));
|
||||
|
||||
let big_or_small = if let FloatErrorKind::PositiveInfinity = sign {
|
||||
"big"
|
||||
} else {
|
||||
"small"
|
||||
};
|
||||
|
||||
alloc.stack(vec![
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("This float literal is too "),
|
||||
alloc.text(big_or_small),
|
||||
alloc.reflow(":"),
|
||||
]),
|
||||
alloc.region(region),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("Roc uses signed 64-bit floating points, allowing values between"),
|
||||
alloc.text(format!("{:e}", f64::MIN)),
|
||||
alloc.reflow(" and "),
|
||||
alloc.text(format!("{:e}", f64::MAX)),
|
||||
]),
|
||||
hint,
|
||||
])
|
||||
}
|
||||
RuntimeError::InvalidFloat(FloatErrorKind::Error, region, _raw_str) => {
|
||||
let hint = alloc
|
||||
.hint()
|
||||
.append(alloc.reflow("Learn more about number literals at TODO"));
|
||||
|
||||
alloc.stack(vec![
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("This float literal contains an invalid digit:"),
|
||||
]),
|
||||
alloc.region(region),
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("Floating point literals can only contain the digits 0-9, or use scientific notation 10e4"),
|
||||
]),
|
||||
hint,
|
||||
])
|
||||
}
|
||||
RuntimeError::InvalidInt(IntErrorKind::Empty, _base, _region, _raw_str) => {
|
||||
unreachable!("would never parse an empty int literal")
|
||||
}
|
||||
RuntimeError::InvalidInt(IntErrorKind::InvalidDigit, base, region, _raw_str) => {
|
||||
use roc_parse::ast::Base::*;
|
||||
|
||||
let name = match base {
|
||||
Decimal => "integer",
|
||||
Octal => "octal integer",
|
||||
Hex => "hex integer",
|
||||
Binary => "binary integer",
|
||||
};
|
||||
|
||||
let plurals = match base {
|
||||
Decimal => "Integer literals",
|
||||
Octal => "Octal (base-8) integer literals",
|
||||
Hex => "Hexadecimal (base-16) integer literals",
|
||||
Binary => "Binary (base-2) integer literals",
|
||||
};
|
||||
|
||||
let charset = match base {
|
||||
Decimal => "0-9",
|
||||
Octal => "0-7",
|
||||
Hex => "0-9, a-f and A-F",
|
||||
Binary => "0 and 1",
|
||||
};
|
||||
|
||||
let hint = alloc
|
||||
.hint()
|
||||
.append(alloc.reflow("Learn more about number literals at TODO"));
|
||||
|
||||
alloc.stack(vec![
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("This "),
|
||||
alloc.text(name),
|
||||
alloc.reflow(" literal contains an invalid digit:"),
|
||||
]),
|
||||
alloc.region(region),
|
||||
alloc.concat(vec![
|
||||
alloc.text(plurals),
|
||||
alloc.reflow(" can only contain the digits "),
|
||||
alloc.text(charset),
|
||||
alloc.text("."),
|
||||
]),
|
||||
hint,
|
||||
])
|
||||
}
|
||||
RuntimeError::InvalidInt(error_kind @ IntErrorKind::Underflow, _base, region, _raw_str)
|
||||
| RuntimeError::InvalidInt(error_kind @ IntErrorKind::Overflow, _base, region, _raw_str) => {
|
||||
let big_or_small = if let IntErrorKind::Underflow = error_kind {
|
||||
"small"
|
||||
} else {
|
||||
"big"
|
||||
};
|
||||
|
||||
let hint = alloc
|
||||
.hint()
|
||||
.append(alloc.reflow("Learn more about number literals at TODO"));
|
||||
|
||||
alloc.stack(vec![
|
||||
alloc.concat(vec![
|
||||
alloc.reflow("This integer literal is too "),
|
||||
alloc.text(big_or_small),
|
||||
alloc.reflow(":"),
|
||||
]),
|
||||
alloc.region(region),
|
||||
alloc.reflow("Roc uses signed 64-bit integers, allowing values between −9_223_372_036_854_775_808 and 9_223_372_036_854_775_807."),
|
||||
hint,
|
||||
])
|
||||
}
|
||||
RuntimeError::NoImplementation => todo!("no implementation, unreachable"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1468,6 +1468,131 @@ mod test_reporting {
|
|||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn malformed_int_pattern() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
when 1 is
|
||||
100A -> 3
|
||||
_ -> 4
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This integer pattern is malformed:
|
||||
|
||||
2 ┆ 100A -> 3
|
||||
┆ ^^^^
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn malformed_float_pattern() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
when 1 is
|
||||
2.X -> 3
|
||||
_ -> 4
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This float pattern is malformed:
|
||||
|
||||
2 ┆ 2.X -> 3
|
||||
┆ ^^^
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn malformed_hex_pattern() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
when 1 is
|
||||
0xZ -> 3
|
||||
_ -> 4
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This hex integer pattern is malformed:
|
||||
|
||||
2 ┆ 0xZ -> 3
|
||||
┆ ^^^
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn malformed_oct_pattern() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
when 1 is
|
||||
0o9 -> 3
|
||||
_ -> 4
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This octal integer pattern is malformed:
|
||||
|
||||
2 ┆ 0o9 -> 3
|
||||
┆ ^^^
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn malformed_bin_pattern() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
when 1 is
|
||||
0b4 -> 3
|
||||
_ -> 4
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This binary integer pattern is malformed:
|
||||
|
||||
2 ┆ 0b4 -> 3
|
||||
┆ ^^^
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_fields() {
|
||||
report_problem_as(
|
||||
|
@ -1702,6 +1827,7 @@ mod test_reporting {
|
|||
|
||||
#[test]
|
||||
fn circular_definition_self() {
|
||||
// invalid recursion
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
|
@ -1723,6 +1849,7 @@ mod test_reporting {
|
|||
|
||||
#[test]
|
||||
fn circular_definition() {
|
||||
// invalid mutual recursion
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
|
@ -2684,6 +2811,85 @@ mod test_reporting {
|
|||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn annotation_definition_mismatch() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
bar : Int
|
||||
foo = \x -> x
|
||||
|
||||
# NOTE: neither bar or foo are defined at this point
|
||||
4
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This annotation does not match the definition immediately following
|
||||
it:
|
||||
|
||||
1 ┆> bar : Int
|
||||
2 ┆> foo = \x -> x
|
||||
|
||||
Is it a typo? If not, put either a newline or comment between them.
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn annotation_newline_body_is_fine() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
bar : Int
|
||||
|
||||
foo = \x -> x
|
||||
|
||||
foo bar
|
||||
"#
|
||||
),
|
||||
indoc!(""),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_alias_rigid_var_pattern() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
MyAlias 1 : Int
|
||||
|
||||
4
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This pattern in the definition of `MyAlias` is not what I expect:
|
||||
|
||||
1 ┆ MyAlias 1 : Int
|
||||
┆ ^
|
||||
|
||||
Only type variables like `a` or `value` can occur in this position.
|
||||
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
`MyAlias` is not used anywhere in your code.
|
||||
|
||||
1 ┆ MyAlias 1 : Int
|
||||
┆ ^^^^^^^^^^^^^^^
|
||||
|
||||
If you didn't intend on using `MyAlias` then remove it so future readers
|
||||
of your code don't wonder why it is there.
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_num() {
|
||||
report_problem_as(
|
||||
|
@ -2918,4 +3124,217 @@ mod test_reporting {
|
|||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integer_out_of_range() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
x = 9_223_372_036_854_775_807_000
|
||||
|
||||
y = -9_223_372_036_854_775_807_000
|
||||
|
||||
h = 0x8FFF_FFFF_FFFF_FFFF
|
||||
l = -0x8FFF_FFFF_FFFF_FFFF
|
||||
|
||||
minlit = -9_223_372_036_854_775_808
|
||||
maxlit = 9_223_372_036_854_775_807
|
||||
|
||||
x + y + h + l + minlit + maxlit
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This integer literal is too small:
|
||||
|
||||
3 ┆ y = -9_223_372_036_854_775_807_000
|
||||
┆ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Roc uses signed 64-bit integers, allowing values between
|
||||
−9_223_372_036_854_775_808 and 9_223_372_036_854_775_807.
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This integer literal is too big:
|
||||
|
||||
5 ┆ h = 0x8FFF_FFFF_FFFF_FFFF
|
||||
┆ ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Roc uses signed 64-bit integers, allowing values between
|
||||
−9_223_372_036_854_775_808 and 9_223_372_036_854_775_807.
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This integer literal is too small:
|
||||
|
||||
6 ┆ l = -0x8FFF_FFFF_FFFF_FFFF
|
||||
┆ ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Roc uses signed 64-bit integers, allowing values between
|
||||
−9_223_372_036_854_775_808 and 9_223_372_036_854_775_807.
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This integer literal is too big:
|
||||
|
||||
1 ┆ x = 9_223_372_036_854_775_807_000
|
||||
┆ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Roc uses signed 64-bit integers, allowing values between
|
||||
−9_223_372_036_854_775_808 and 9_223_372_036_854_775_807.
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float_out_of_range() {
|
||||
report_problem_as(
|
||||
&format!(
|
||||
r#"
|
||||
overflow = 1{:e}
|
||||
underflow = -1{:e}
|
||||
|
||||
overflow + underflow
|
||||
"#,
|
||||
f64::MAX,
|
||||
f64::MAX,
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This float literal is too small:
|
||||
|
||||
3 ┆ underflow = -11.7976931348623157e308
|
||||
┆ ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Roc uses signed 64-bit floating points, allowing values
|
||||
between-1.7976931348623157e308 and 1.7976931348623157e308
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This float literal is too big:
|
||||
|
||||
2 ┆ overflow = 11.7976931348623157e308
|
||||
┆ ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Roc uses signed 64-bit floating points, allowing values
|
||||
between-1.7976931348623157e308 and 1.7976931348623157e308
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integer_malformed() {
|
||||
// the generated messages here are incorrect. Waiting for a rust nightly feature to land,
|
||||
// see https://github.com/rust-lang/rust/issues/22639
|
||||
// this test is here to spot regressions in error reporting
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
dec = 100A
|
||||
|
||||
hex = 0xZZZ
|
||||
|
||||
oct = 0o9
|
||||
|
||||
bin = 0b2
|
||||
|
||||
dec + hex + oct + bin
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This hex integer literal contains an invalid digit:
|
||||
|
||||
3 ┆ hex = 0xZZZ
|
||||
┆ ^^^^^
|
||||
|
||||
Hexadecimal (base-16) integer literals can only contain the digits
|
||||
0-9, a-f and A-F.
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This octal integer literal contains an invalid digit:
|
||||
|
||||
5 ┆ oct = 0o9
|
||||
┆ ^^^
|
||||
|
||||
Octal (base-8) integer literals can only contain the digits 0-7.
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This binary integer literal contains an invalid digit:
|
||||
|
||||
7 ┆ bin = 0b2
|
||||
┆ ^^^
|
||||
|
||||
Binary (base-2) integer literals can only contain the digits 0 and 1.
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This integer literal contains an invalid digit:
|
||||
|
||||
1 ┆ dec = 100A
|
||||
┆ ^^^^
|
||||
|
||||
Integer literals can only contain the digits 0-9.
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn float_malformed() {
|
||||
report_problem_as(
|
||||
indoc!(
|
||||
r#"
|
||||
x = 3.0A
|
||||
|
||||
x
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
r#"
|
||||
-- SYNTAX PROBLEM --------------------------------------------------------------
|
||||
|
||||
This float literal contains an invalid digit:
|
||||
|
||||
1 ┆ x = 3.0A
|
||||
┆ ^^^^
|
||||
|
||||
Floating point literals can only contain the digits 0-9, or use
|
||||
scientific notation 10e4
|
||||
|
||||
Hint: Learn more about number literals at TODO
|
||||
"#
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue