Merge remote-tracking branch 'origin/trunk' into low-level-ops

This commit is contained in:
Richard Feldman 2020-07-07 21:02:03 -04:00
commit 1cd49689c2
29 changed files with 1630 additions and 440 deletions

View file

@ -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"),
}
}