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