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}