1use crate::status::LuaStatus;
4use crate::value::LuaValue;
5use std::fmt;
6
7#[derive(Debug, Clone)]
10pub enum LuaError {
11 Runtime(LuaValue),
12 Syntax(LuaValue),
13 Memory,
14 Error,
15 Yield,
16 File,
17 Gc,
18}
19
20impl LuaError {
21 pub fn runtime(args: fmt::Arguments<'_>) -> Self {
23 LuaError::Runtime(LuaValue::Str(crate::gc::GcRef::new(
24 crate::string::LuaString::from_bytes(format!("{}", args).into_bytes()),
25 )))
26 }
27 pub fn syntax(args: fmt::Arguments<'_>) -> Self {
28 LuaError::Syntax(LuaValue::Str(crate::gc::GcRef::new(
29 crate::string::LuaString::from_bytes(format!("{}", args).into_bytes()),
30 )))
31 }
32 pub fn syntax_at(args: fmt::Arguments<'_>, source: &[u8], line: i32) -> Self {
33 LuaError::Syntax(LuaValue::Str(crate::gc::GcRef::new(
34 crate::string::LuaString::from_bytes(
35 format!("{}:{}: {}", String::from_utf8_lossy(source), line, args).into_bytes()
36 ),
37 )))
38 }
39 pub fn syntax_raw(msg: &[u8]) -> Self {
40 LuaError::Syntax(LuaValue::Str(crate::gc::GcRef::new(
41 crate::string::LuaString::from_bytes(msg.to_vec()),
42 )))
43 }
44
45 pub fn type_error(v: &LuaValue, op: &str) -> Self {
47 LuaError::runtime(format_args!("attempt to {} a {} value", op, v.type_name()))
48 }
49 pub fn call_error(v: &LuaValue) -> Self {
50 Self::type_error(v, "call")
51 }
52 pub fn concat_error(p1: &LuaValue, p2: &LuaValue) -> Self {
53 let bad = if matches!(p1, LuaValue::Str(_) | LuaValue::Int(_) | LuaValue::Float(_)) { p2 } else { p1 };
54 LuaError::runtime(format_args!("attempt to concatenate a {} value", bad.type_name()))
55 }
56 pub fn arith_error(p1: &LuaValue, p2: &LuaValue, _msg: &str) -> Self {
57 let bad = if matches!(p1, LuaValue::Int(_) | LuaValue::Float(_)) { p2 } else { p1 };
58 LuaError::runtime(format_args!("attempt to perform arithmetic on a {} value", bad.type_name()))
59 }
60 pub fn int_overflow(_p1: &LuaValue, _p2: &LuaValue) -> Self {
61 LuaError::runtime(format_args!("number has no integer representation"))
62 }
63 pub fn order_error(p1: &LuaValue, p2: &LuaValue) -> Self {
64 LuaError::runtime(format_args!("attempt to compare {} with {}", p1.type_name(), p2.type_name()))
65 }
66 pub fn for_error(v: &LuaValue, what: &str) -> Self {
67 LuaError::runtime(format_args!("bad 'for' {} (number expected, got {})", what, v.type_name()))
68 }
69 pub fn arg_error(narg: i32, msg: &str) -> Self {
70 LuaError::runtime(format_args!("bad argument #{} ({})", narg, msg))
71 }
72 pub fn type_arg_error(narg: i32, expected: &str, got: &LuaValue) -> Self {
73 LuaError::runtime(format_args!("bad argument #{} ({} expected, got {})", narg, expected, got.type_name()))
74 }
75
76 pub fn from_value(v: LuaValue) -> Self {
78 LuaError::Runtime(v)
81 }
82 pub fn with_status(status: LuaStatus) -> Self {
83 match status {
84 LuaStatus::Ok => LuaError::Error,
85 LuaStatus::Yield => LuaError::Yield,
86 LuaStatus::ErrRun => LuaError::Runtime(LuaValue::Nil),
87 LuaStatus::ErrSyntax => LuaError::Syntax(LuaValue::Nil),
88 LuaStatus::ErrMem => LuaError::Memory,
89 LuaStatus::ErrErr => LuaError::Error,
90 LuaStatus::ErrFile => LuaError::File,
91 LuaStatus::ErrGc => LuaError::Gc,
92 }
93 }
94
95 pub fn to_status(&self) -> LuaStatus {
96 match self {
97 LuaError::Runtime(_) => LuaStatus::ErrRun,
98 LuaError::Syntax(_) => LuaStatus::ErrSyntax,
99 LuaError::Memory => LuaStatus::ErrMem,
100 LuaError::Error => LuaStatus::ErrErr,
101 LuaError::Yield => LuaStatus::Yield,
102 LuaError::File => LuaStatus::ErrFile,
103 LuaError::Gc => LuaStatus::ErrGc,
104 }
105 }
106
107 pub fn into_value(self) -> LuaValue {
108 match self {
109 LuaError::Runtime(v) | LuaError::Syntax(v) => v,
110 _ => LuaValue::Nil,
111 }
112 }
113}
114
115impl fmt::Display for LuaError {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 write!(f, "{:?}", self)
118 }
119}
120impl std::error::Error for LuaError {}
121
122