Skip to main content

mrubyedge/
error.rs

1use std::error;
2use std::fmt;
3use std::rc::Rc;
4
5use crate::yamrb::value::RClass;
6use crate::yamrb::value::RObject;
7use crate::yamrb::vm::VM;
8
9#[derive(Debug, Clone, PartialEq)]
10pub enum Error {
11    General,
12    Internal(String),
13    InvalidOpCode,
14    RuntimeError(String),
15    ArgumentError(String),
16    RangeError(String),
17    TypeMismatch,
18    NoMethodError(String),
19    NameError(String),
20    ZeroDivisionError,
21
22    TaggedError(&'static str, String),
23
24    Break(Rc<RObject>),
25    BlockReturn(usize, Rc<RObject>),
26}
27
28impl fmt::Display for Error {
29    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
30        write!(f, "error nr {:?}", self)
31    }
32}
33
34impl error::Error for Error {}
35
36impl Error {
37    pub fn internal(msg: impl Into<String>) -> Error {
38        Error::Internal(msg.into())
39    }
40
41    pub fn message(&self) -> String {
42        match self {
43            Error::General => "General error".to_string(),
44            Error::Internal(msg) => format!("[Internal Error] {}", msg.clone()),
45            Error::InvalidOpCode => "Invalid opcode".to_string(),
46            Error::RuntimeError(msg) => msg.clone(),
47            Error::ArgumentError(msg) => format!("Invalid argument: {}", msg),
48            Error::RangeError(msg) => format!("Out of range: {}", msg),
49            Error::TypeMismatch => "Type mismatch".to_string(),
50            Error::NoMethodError(msg) => format!("Method not found: {}", msg),
51            Error::NameError(msg) => format!("Cannot found name: {}", msg),
52            Error::ZeroDivisionError => "divided by 0".to_string(),
53
54            Error::TaggedError(tag, msg) => format!("[{}] {}", tag, msg),
55
56            Error::Break(_) => "[Break]".to_string(),
57            Error::BlockReturn(_, _) => "[BlockReturn]".to_string(),
58        }
59    }
60
61    pub fn is_instance_of(&self, other: Rc<RClass>) -> bool {
62        matches!(
63            (self, other.sym_id.name.as_str()),
64            (Error::General, "StandardError")
65                | (Error::Internal(_), "InternalError")
66                | (Error::InvalidOpCode, "StandardError")
67                | (Error::RuntimeError(_), "RuntimeError")
68                | (Error::ArgumentError(_), "ArgumentError")
69                | (Error::RangeError(_), "RangeError")
70                | (Error::TypeMismatch, "StandardError")
71                | (Error::NoMethodError(_), "NoMethodError")
72                | (Error::NameError(_), "NameError")
73                | (Error::ZeroDivisionError, "ZeroDivisionError")
74        )
75    }
76
77    pub fn is_a(&self, vm: &mut VM, other: Rc<RClass>) -> bool {
78        let mut klass: Option<Rc<RClass>> = RClass::from_error(vm, self).into();
79        let target_klass_name = other.sym_id.name.as_str();
80
81        while let Some(k) = klass {
82            if k.sym_id.name.as_str() == target_klass_name {
83                return true;
84            }
85            klass = k.super_class.clone();
86        }
87        false
88    }
89}
90
91/// Used for asynchronous or multithreaded context
92#[derive(Debug, Clone, PartialEq)]
93pub enum StaticError {
94    General(String),
95}
96
97impl fmt::Display for StaticError {
98    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
99        write!(f, "error nr {:?}", self)
100    }
101}
102
103impl error::Error for StaticError {}
104
105unsafe impl Sync for StaticError {}
106unsafe impl Send for StaticError {}
107
108impl From<Error> for StaticError {
109    fn from(err: Error) -> StaticError {
110        match err {
111            Error::General => StaticError::General("General error".to_string()),
112            Error::Internal(msg) => StaticError::General(format!("[Internal Error] {}", msg)),
113            Error::InvalidOpCode => StaticError::General("Invalid opcode".to_string()),
114            Error::RuntimeError(msg) => StaticError::General(msg),
115            Error::ArgumentError(msg) => StaticError::General(format!("Invalid argument: {}", msg)),
116            Error::RangeError(msg) => StaticError::General(format!("Out of range: {}", msg)),
117            Error::TypeMismatch => StaticError::General("Type mismatch".to_string()),
118            Error::NoMethodError(msg) => StaticError::General(format!("Method not found: {}", msg)),
119            Error::NameError(msg) => StaticError::General(format!("Cannot found name: {}", msg)),
120            Error::ZeroDivisionError => StaticError::General("divided by 0".to_string()),
121
122            Error::TaggedError(tag, msg) => StaticError::General(format!("[{}] {}", tag, msg)),
123
124            Error::Break(_) => StaticError::General("[Break]".to_string()),
125            Error::BlockReturn(_, _) => StaticError::General("[BlockReturn]".to_string()),
126        }
127    }
128}