1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
/* * mini-haskell: light-weight Haskell for fun * Copyright (C) 2020 Xie Ruifeng * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ //! error reporting for the mini-Haskell compiler. use num_bigint::BigInt; use crate::lexeme::LexemeType; use crate::scanner::{LexError, Location, Range}; /// An exhaustive list of compiler errors. #[derive(Debug)] pub enum Error { /// An invalid UTF-8 sequence. InvalidUTF8(Vec<u8>), /// A failure during the input process. InputFailure(std::io::Error), /// A Unicode character not accepted by the Haskell language. InvalidChar(char), /// An error during the tokenization process. InvalidToken(LexError), /// A lexeme ended prematurely, e.g. EOF in a block comment. IncompleteLexeme(LexemeType), /// A float literal is too large (or small) to represent. /// /// **Note**: /// /// - maximum value for IEEE 754 64-bit double is approximately 1.8e308; /// - to prevent loss of precision, maximum value to store in IEEE 754 64-bit double is 2^53; /// - `Rational` with an exponent 4096 takes approximately 13.3KiB to store; /// - large float literals may eventually exhaust the usable memory of the compiler; /// - `Rational` is probably not a good representation for large floats; FloatOutOfBound(BigInt), /// A character/string literal contains a Unicode character out of bound. CharOutOfBound(BigInt), } /// A diagnostic message (body). #[derive(Debug)] pub enum DiagnosticMessage { /// Critical errors. Error(Error), } /// A diagnostic, with a source location, and an optional source range. #[derive(Debug)] pub struct Diagnostic { location: Location, range: Option<Range>, message: DiagnosticMessage, } impl Diagnostic { /// Create a new diagnostics. pub fn new(location: Location, message: DiagnosticMessage) -> Diagnostic { Diagnostic { location, message, range: None } } /// Add a source range to the report. pub fn within_range(self, range: Range) -> Self { Self { range: Some(range), ..self } } /// Add a source range from a `[begin, end)` pair to the report. pub fn within(self, begin: Location, end: Location) -> Self { Self { range: Some(Range { begin, end }), ..self } } /// Report to the diagnostics engine. pub fn report(self, engine: &mut DiagnosticsEngine) { engine.push(self) } } /// The diagnostics engine. pub type DiagnosticsEngine = Vec<Diagnostic>;