ocypode_lang/
errors.rs

1use crate::{ast, diagnostics, parser::Rule};
2use miette::{GraphicalReportHandler, JSONReportHandler};
3use pest::error::InputLocation;
4
5/// The result type with the error.
6pub type Result<T> = std::result::Result<T, Error>;
7
8/// The error type.
9#[derive(Debug, Clone)]
10#[non_exhaustive]
11pub enum ErrorKind {
12    /// The name of the ident is invalid.
13    /// - The first argument is the invalid name.
14    /// - The second argument is the reason.
15    /// - The third argument is the valid name.
16    /// - The fourth argument is the statement type.
17    InvalidName(String, String, String, String),
18    /// The main function is invalid.
19    /// - The first argument is the reason.
20    /// - The second argument is the help message.
21    InvalidMainFunction(String, String),
22    /// The ident is undeclared.
23    /// - The first argument is the name of the ident.
24    UnDeclaredIdent(String),
25    /// Alreade decleared function.
26    /// - The first argument is the name of the ident.
27    /// - The second argument is the span of the old declaration.
28    /// (The span of the new declaration is stored in the error.)
29    AlreadyDeclared(String, (usize, usize)),
30    /// Missing main function.
31    /// (The span of the error will not be used.)
32    MissingMainFunction,
33    /// The exit code is invalid.
34    /// - The first argument is the exit code.
35    InvalidExitCode(bigdecimal::BigDecimal),
36    /// The ident is not callable.
37    /// - The first argument is the span of the call
38    /// (The span of the error is the not callable ident.)
39    NotCallable((usize, usize)),
40    /// Uncorrect arguments.
41    /// - The first argument is the number of arguments.
42    /// - The second argument is the span of the called function.
43    /// - The third argument is the parametets of the called function.
44    /// - The forth argument is the name of the called function.
45    /// (The span of the error is the function call expression.)
46    UncorrectArguments(usize, (usize, usize), Vec<ast::Param>, String),
47    /// Unexpected type.
48    /// - The first argument is the expected type.
49    /// - The second argument is the actual type.
50    /// (The span of the error is the expression.)
51    UnexpectedType(String, String),
52    /// Multiple packed params.
53    /// - The first argument is the name of the function.
54    /// (The span of the error is the parametets of the function.)
55    MultiplePackedParams(String),
56    /// Packed param is not last.
57    /// - The first argument is the name of the packed param.
58    /// (The span of the error is the packed param.)
59    PackedParamNotLast(String),
60    /// Multiple params with the same name.
61    /// - The first argument is the name of the param.
62    /// - The second argument is the name of the function.
63    /// (The span of the error is the parametets of the function.)
64    MultipleParamsWithTheSameName(String, String),
65    /// Invalid unpacked argument.
66    /// - The first argument is the name of the argument type.
67    InvalidUnpackArg(String),
68    /// Format error.
69    /// - The first argument is the reason.
70    /// - The second argument is the help message.
71    FormatError(String, String),
72    /// Runtime error. (The error is not a bug in the interpreter.)
73    /// - The first argument is the reason.
74    Runtime(String),
75    /// The parser error.
76    Parse(String),
77}
78
79/// The error type.
80#[derive(Debug, Clone)]
81pub struct Error {
82    pub kind: ErrorKind,
83    pub span: miette::SourceSpan,
84}
85
86pub trait SpanError {
87    fn span(&self) -> (usize, usize);
88}
89
90impl SpanError for ast::Span {
91    fn span(&self) -> (usize, usize) {
92        let (start, end) = (self.start, self.end);
93        let length = end - start;
94        (start, length)
95    }
96}
97
98impl SpanError for pest::Span<'_> {
99    fn span(&self) -> (usize, usize) {
100        let (start, end) = (self.start(), self.end());
101        let length = end - start;
102        (start, length)
103    }
104}
105
106impl SpanError for InputLocation {
107    fn span(&self) -> (usize, usize) {
108        match self {
109            InputLocation::Pos(pos) => (*pos, 1),
110            InputLocation::Span((start, end)) => (*start, end - start),
111        }
112    }
113}
114
115impl SpanError for (usize, usize) {
116    fn span(&self) -> (usize, usize) {
117        let (start, end) = self;
118        let length = end - start;
119        (*start, length)
120    }
121}
122
123impl Error {
124    /// Create a new error.
125    pub fn new(kind: ErrorKind, span: impl SpanError) -> Self {
126        Self {
127            kind,
128            span: span.span().into(),
129        }
130    }
131
132    /// Returns a diagnostic for this error.
133    pub fn as_diagnostic(
134        self,
135        source: impl AsRef<str>,
136        source_name: impl AsRef<str>,
137    ) -> diagnostics::Diagnostic<GraphicalReportHandler> {
138        diagnostics::as_diagnostic::<GraphicalReportHandler>(
139            self,
140            source.as_ref().to_string(),
141            source_name.as_ref().to_string(),
142        )
143        .rgb()
144    }
145
146    /// Returns a json diagnostic for this error.
147    pub fn as_json_diagnostic(
148        self,
149        source: impl AsRef<str>,
150        source_name: impl AsRef<str>,
151    ) -> diagnostics::Diagnostic<JSONReportHandler> {
152        diagnostics::as_diagnostic::<JSONReportHandler>(
153            self,
154            source.as_ref().to_string(),
155            source_name.as_ref().to_string(),
156        )
157    }
158}
159
160impl From<pest::error::Error<Rule>> for Error {
161    fn from(err: pest::error::Error<Rule>) -> Self {
162        Self::new(
163            ErrorKind::Parse(err.variant.message().to_string()),
164            err.location,
165        )
166    }
167}