Skip to main content

unlab_gpu/
error.rs

1//
2// Copyright (c) 2025-2026 Ɓukasz Szpakowski
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at https://mozilla.org/MPL/2.0/.
7//
8//! An error module.
9use std::error;
10use std::fmt;
11use std::io;
12use std::path::PathBuf;
13use std::result;
14use std::sync::Arc;
15use crate::ctrlc;
16use crate::curl;
17use crate::serde_json;
18use crate::toml;
19use crate::matrix;
20use crate::pkg::PkgName;
21use crate::value::Value;
22
23/// A structure of file position.
24#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
25pub struct Pos
26{
27    /// A path to the file.
28    pub path: Arc<String>,
29    /// A line in the file
30    pub line: u64,
31    /// A column in the file.
32    pub column: usize,
33}
34
35impl Pos
36{
37    /// Creates a file position.
38    pub fn new(path: Arc<String>, line: u64, column: usize) -> Self
39    { Pos { path, line, column, } }
40}
41
42/// An enumeration of parser EOF flag.
43///
44/// The parser EOF flag determines whether a interactive main loop should read next line if
45/// unexpected EOF occurs while parsing.
46#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
47pub enum ParserEofFlag
48{
49    /// No a repetition, e.i. next line shouldn't be read.
50    NoRepetition,
51    /// A repetition, e.i. next line should be read.
52    Repetition,
53}
54
55/// An enumeration of package path conflicts.
56#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
57pub enum PkgPathConflict
58{
59    /// A bin directory.
60    Bin,
61    /// A lib directory.
62    Lib,
63    /// A doc directory.
64    Doc,
65}
66
67/// An enumeration of stop type.
68#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
69pub enum Stop
70{
71    /// A stop by a `break` statement.
72    Break,
73    /// A stop by a `continue` statement.
74    Continue,
75    /// A stop by a `return` statement.
76    Return,
77    /// A stop by a `quit` statement.
78    Quit,
79    /// A stop by an error propagation.
80    ErrorPropagation,
81    /// A stop by an exit built-in function. 
82    Exit(i32),
83}
84
85/// An error enumeration.
86#[derive(Debug)]
87pub enum Error
88{
89    /// A parser I/O error.
90    ParserIo(Arc<String>, io::Error),
91    /// A parser EOF error.
92    ParserEof(Arc<String>, ParserEofFlag),
93    /// A parser error.
94    Parser(Pos, String),
95    /// An interpreter error.
96    Interp(String),
97    /// A package error.
98    Pkg(String),
99    /// A package error with package name.
100    PkgName(PkgName, String),
101    /// An error of package depenency cycle.
102    PkgDepCycle(Vec<PkgName>),
103    /// An error of package path conflicts.
104    PkgPathConflicts(PkgName, Option<PkgName>, Vec<PathBuf>, PkgPathConflict),
105    ///  A tester error.
106    Tester(String),
107    /// A matrix error.
108    Matrix(matrix::Error),
109    /// A mutex can't be locked.
110    Mutex,
111    /// A reader-writer lock can't be read.
112    RwLockRead,
113    /// A reader-writer lock can't be written.
114    RwLockWrite,
115    /// An object can't be received.
116    Recv,
117    /// A module node is already added.
118    AlreadyAddedModNode,
119    /// No a function module.
120    NoFunMod,
121    /// No a documentation module.
122    NoDocMod,
123    /// An I/O error.
124    Io(io::Error),
125    /// A ctrlc error.
126    Ctrlc(ctrlc::Error),
127    /// A toml error for deserialization.
128    TomlDe(toml::de::Error),
129    /// A toml error for Serialization.
130    TomlSer(toml::ser::Error),
131    /// A winit error.
132    Winit(Box<dyn error::Error>),
133    /// A jammdb error.
134    Jammdb(Box<dyn error::Error>),
135    /// A zip error.
136    Zip(Box<dyn error::Error>),
137    /// A curl error.
138    Curl(curl::Error),
139    /// A serde_json error.
140    SerdeJson(serde_json::Error),
141    /// A latex2mathml error.
142    Latex2mathml(Box<dyn error::Error>),
143    /// A markdown error.
144    Markdown(String),
145    /// An opener error.
146    Opener(Box<dyn error::Error>),
147    /// A version is invalid.
148    InvalidVersion,
149    /// A package name is invalid.
150    InvalidPkgName,
151    /// No an OpenCL backend.
152    NoOpenClBackend,
153    /// No a CUDA backend.
154    NoCudaBackend,
155    /// A stop error that is used by an interpreter.
156    Stop(Stop),
157    /// An interruption is occurred.
158    Intr,
159    /// An assertion error.
160    Assert(Option<String>, Option<(Value, Value)>),
161}
162
163impl error::Error for Error
164{}
165
166impl fmt::Display for Error
167{
168    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
169    {
170        match self {
171            Error::ParserIo(path, err) => write!(f, "{}: i/o error: {}", path, err),
172            Error::ParserEof(path, _) => write!(f, "{}: end of file", path),
173            Error::Parser(pos, msg) => write!(f, "{}: {}.{}: {}", pos.path, pos.line, pos.column, msg),
174            Error::Interp(msg) => write!(f, "{}", msg),
175            Error::Pkg(msg) => write!(f, "{}", msg),
176            Error::PkgName(name, msg) => write!(f, "{}: {}", name, msg),
177            Error::PkgDepCycle(names) => {
178                write!(f, "occurred cycle of dependencies: ")?;
179                let mut is_first = true;
180                for name in names {
181                    if !is_first {
182                        write!(f, " -> ")?;
183                    }
184                    write!(f, "{}", name)?;
185                    is_first = false;
186                }
187                Ok(())
188            },
189            Error::PkgPathConflicts(name, name2, conflict_paths, conflict) => {
190                let conflict_name = match conflict {
191                    PkgPathConflict::Bin => "bin",
192                    PkgPathConflict::Lib => "lib",
193                    PkgPathConflict::Doc => "doc",
194                };
195                match name2 {
196                    Some(name2) => write!(f, "occurred conflicts between {} and {} for directory {}:", name, name2, conflict_name)?,
197                    None => write!(f, "occurred conflicts between {} and installed packages for directory {}:", name, conflict_name)?,
198                }
199                for conflict_path in conflict_paths {
200                    write!(f, "\n{}", conflict_path.to_string_lossy().into_owned())?;
201                }
202                Ok(())
203            },
204            Error::Tester(msg) => write!(f, "{}", msg),
205            Error::Matrix(err) => write!(f, "matrix error: {}", err),
206            Error::Mutex => write!(f, "can't lock mutex"),
207            Error::RwLockRead => write!(f, "can't read rw lock"),
208            Error::RwLockWrite => write!(f, "can't write rw lock"),
209            Error::Recv => write!(f, "can't receive object"),
210            Error::AlreadyAddedModNode => write!(f, "already added module node"),
211            Error::NoFunMod => write!(f, "no function module"),
212            Error::NoDocMod => write!(f, "no documentation module"),
213            Error::Io(err) => write!(f, "i/o error: {}", err),
214            Error::Ctrlc(err) => write!(f, "ctrl-c error: {}", err),
215            Error::TomlDe(err) => write!(f, "toml error: {}", err),
216            Error::TomlSer(err) => write!(f, "toml error: {}", err),
217            Error::Winit(err) => write!(f, "winit error: {}", err),
218            Error::Jammdb(err) => write!(f, "jammdb error: {}", err),
219            Error::Zip(err) => write!(f, "zip error: {}", err),
220            Error::Curl(err) => write!(f, "curl error: {}", err),
221            Error::SerdeJson(err) => write!(f, "serde_json error: {}", err),
222            Error::Latex2mathml(err) =>  write!(f, "latex2mathml error: {}", err),
223            Error::Markdown(msg) =>  write!(f, "markdown error: {}", msg),
224            Error::Opener(err) => write!(f, "opener error: {}", err),
225            Error::InvalidVersion => write!(f, "invalid version"),
226            Error::InvalidPkgName => write!(f, "invalid package name"),
227            Error::NoOpenClBackend => write!(f, "no OpenCL backend"),
228            Error::NoCudaBackend => write!(f, "no CUDA backend"),
229            Error::Stop(Stop::Break) => write!(f, "stopped by break"),
230            Error::Stop(Stop::Continue) => write!(f, "stopped by continue"),
231            Error::Stop(Stop::Return) => write!(f, "stopped by return"),
232            Error::Stop(Stop::Quit) => write!(f, "stopped by quit"),
233            Error::Stop(Stop::ErrorPropagation) => write!(f, "stopped by error propagation"),
234            Error::Stop(Stop::Exit(code)) => write!(f, "stopped by exit with code {}", code),
235            Error::Intr => write!(f, "interrupted"),
236            Error::Assert(msg, pair) => {
237                match msg {
238                    Some(msg) => write!(f, "assertion failed: {}", msg)?,
239                    None => write!(f, "assertion failed")?,
240                }
241                match pair {
242                    Some((left, right)) => {
243                        write!(f, "\nleft:   {}", left)?;
244                        write!(f, "\nright:  {}", right)?;
245                    },
246                    None => (),
247                }
248                Ok(())
249            },
250        }
251    }
252}
253
254/// A result type.
255pub type Result<T> = result::Result<T, Error>;