1#![warn(missing_docs)]
6
7use std::sync::Arc;
8
9#[derive(Debug, Clone, PartialEq)]
11pub enum PythonValue {
12 None,
14 Boolean(bool),
16 Integer(i64),
18 Float(f64),
20 String(String),
22 List(Vec<Arc<PythonValue>>),
24 Tuple(Vec<Arc<PythonValue>>),
26 Dict(std::collections::HashMap<String, Arc<PythonValue>>),
28 Object(String, std::collections::HashMap<String, Arc<PythonValue>>),
30 Function(String),
32}
33
34impl PythonValue {
35 pub fn is_none(&self) -> bool {
37 matches!(self, PythonValue::None)
38 }
39
40 pub fn to_i64(&self) -> i64 {
42 match self {
43 PythonValue::Integer(i) => *i,
44 PythonValue::Float(f) => *f as i64,
45 PythonValue::Boolean(b) => {
46 if *b {
47 1
48 }
49 else {
50 0
51 }
52 }
53 _ => 0,
54 }
55 }
56
57 pub fn to_f64(&self) -> f64 {
59 match self {
60 PythonValue::Float(f) => *f,
61 PythonValue::Integer(i) => *i as f64,
62 PythonValue::Boolean(b) => {
63 if *b {
64 1.0
65 }
66 else {
67 0.0
68 }
69 }
70 _ => 0.0,
71 }
72 }
73
74 pub fn to_bool(&self) -> bool {
76 match self {
77 PythonValue::None => false,
78 PythonValue::Boolean(b) => *b,
79 PythonValue::Integer(i) => *i != 0,
80 PythonValue::Float(f) => *f != 0.0,
81 PythonValue::String(s) => !s.is_empty(),
82 PythonValue::List(l) => !l.is_empty(),
83 PythonValue::Tuple(t) => !t.is_empty(),
84 PythonValue::Dict(d) => !d.is_empty(),
85 _ => true,
86 }
87 }
88
89 pub fn to_string(&self) -> String {
91 match self {
92 PythonValue::String(s) => s.clone(),
93 PythonValue::Integer(i) => i.to_string(),
94 PythonValue::Float(f) => f.to_string(),
95 PythonValue::Boolean(b) => b.to_string(),
96 PythonValue::None => "None".to_string(),
97 PythonValue::List(l) => format!("{:?}", l),
98 PythonValue::Tuple(t) => format!("{:?}", t),
99 PythonValue::Dict(d) => format!("{:?}", d),
100 PythonValue::Object(name, _) => format!("<{} object>", name),
101 PythonValue::Function(name) => format!("<function {}>", name),
102 }
103 }
104
105 pub fn len(&self) -> usize {
107 match self {
108 PythonValue::List(l) => l.len(),
109 PythonValue::Tuple(t) => t.len(),
110 PythonValue::Dict(d) => d.len(),
111 PythonValue::String(s) => s.len(),
112 _ => 0,
113 }
114 }
115
116 pub fn get_item(&self, index: &PythonValue) -> PythonResult<Arc<PythonValue>> {
118 match (self, index) {
119 (PythonValue::List(l), PythonValue::Integer(i)) => {
120 let idx = *i as usize;
121 if idx < l.len() {
122 Ok(l[idx].clone())
123 }
124 else {
125 Err(PythonError::IndexError(format!("list index out of range: {}", i)))
126 }
127 }
128 (PythonValue::Tuple(t), PythonValue::Integer(i)) => {
129 let idx = *i as usize;
130 if idx < t.len() {
131 Ok(t[idx].clone())
132 }
133 else {
134 Err(PythonError::IndexError(format!("tuple index out of range: {}", i)))
135 }
136 }
137 (PythonValue::Dict(d), PythonValue::String(key)) => {
138 if let Some(value) = d.get(key) {
139 Ok(value.clone())
140 }
141 else {
142 Err(PythonError::KeyError(key.clone()))
143 }
144 }
145 (PythonValue::String(s), PythonValue::Integer(i)) => {
146 let idx = *i as usize;
147 if idx < s.len() {
148 Ok(Arc::new(PythonValue::String(s.chars().nth(idx).unwrap().to_string())))
149 }
150 else {
151 Err(PythonError::IndexError(format!("string index out of range: {}", i)))
152 }
153 }
154 _ => Err(PythonError::TypeError("unsupported operand type(s) for []".to_string())),
155 }
156 }
157
158 pub fn set_item(&mut self, index: &PythonValue, value: Arc<PythonValue>) -> PythonResult<()> {
160 match (self, index) {
161 (PythonValue::List(l), PythonValue::Integer(i)) => {
162 let idx = *i as usize;
163 if idx < l.len() {
164 l[idx] = value;
165 Ok(())
166 }
167 else {
168 Err(PythonError::IndexError(format!("list assignment index out of range: {}", i)))
169 }
170 }
171 (PythonValue::Dict(d), PythonValue::String(key)) => {
172 d.insert(key.clone(), value);
173 Ok(())
174 }
175 _ => Err(PythonError::TypeError("unsupported assignment to type".to_string())),
176 }
177 }
178
179 pub fn append(&mut self, value: Arc<PythonValue>) -> PythonResult<()> {
181 match self {
182 PythonValue::List(l) => {
183 l.push(value);
184 Ok(())
185 }
186 _ => Err(PythonError::TypeError("append() takes exactly one argument (0 given)".to_string())),
187 }
188 }
189
190 pub fn add(&self, other: &PythonValue) -> PythonResult<PythonValue> {
192 match (self, other) {
193 (PythonValue::Integer(a), PythonValue::Integer(b)) => Ok(PythonValue::Integer(a + b)),
194 (PythonValue::Integer(a), PythonValue::Float(b)) => Ok(PythonValue::Float((*a as f64) + *b)),
195 (PythonValue::Float(a), PythonValue::Integer(b)) => Ok(PythonValue::Float(*a + (*b as f64))),
196 (PythonValue::Float(a), PythonValue::Float(b)) => Ok(PythonValue::Float(*a + *b)),
197 (PythonValue::String(a), PythonValue::String(b)) => Ok(PythonValue::String(format!("{}{}", a, b))),
198 (PythonValue::List(a), PythonValue::List(b)) => {
199 let mut result = a.clone();
200 result.extend(b.clone());
201 Ok(PythonValue::List(result))
202 }
203 (PythonValue::Tuple(a), PythonValue::Tuple(b)) => {
204 let mut result = a.clone();
205 result.extend(b.clone());
206 Ok(PythonValue::Tuple(result))
207 }
208 _ => Err(PythonError::TypeError("unsupported operand type(s) for +".to_string())),
209 }
210 }
211
212 pub fn sub(&self, other: &PythonValue) -> PythonResult<PythonValue> {
214 match (self, other) {
215 (PythonValue::Integer(a), PythonValue::Integer(b)) => Ok(PythonValue::Integer(a - b)),
216 (PythonValue::Integer(a), PythonValue::Float(b)) => Ok(PythonValue::Float((*a as f64) - *b)),
217 (PythonValue::Float(a), PythonValue::Integer(b)) => Ok(PythonValue::Float(*a - (*b as f64))),
218 (PythonValue::Float(a), PythonValue::Float(b)) => Ok(PythonValue::Float(*a - *b)),
219 _ => Err(PythonError::TypeError("unsupported operand type(s) for -".to_string())),
220 }
221 }
222
223 pub fn mul(&self, other: &PythonValue) -> PythonResult<PythonValue> {
225 match (self, other) {
226 (PythonValue::Integer(a), PythonValue::Integer(b)) => Ok(PythonValue::Integer(a * b)),
227 (PythonValue::Integer(a), PythonValue::Float(b)) => Ok(PythonValue::Float((*a as f64) * *b)),
228 (PythonValue::Float(a), PythonValue::Integer(b)) => Ok(PythonValue::Float(*a * (*b as f64))),
229 (PythonValue::Float(a), PythonValue::Float(b)) => Ok(PythonValue::Float(*a * *b)),
230 (PythonValue::String(a), PythonValue::Integer(b)) => {
231 if *b >= 0 {
232 Ok(PythonValue::String(a.repeat(*b as usize)))
233 }
234 else {
235 Ok(PythonValue::String("".to_string()))
236 }
237 }
238 (PythonValue::List(a), PythonValue::Integer(b)) => {
239 if *b >= 0 {
240 let mut result = Vec::new();
241 for _ in 0..*b {
242 result.extend(a.clone());
243 }
244 Ok(PythonValue::List(result))
245 }
246 else {
247 Ok(PythonValue::List(Vec::new()))
248 }
249 }
250 (PythonValue::Tuple(a), PythonValue::Integer(b)) => {
251 if *b >= 0 {
252 let mut result = Vec::new();
253 for _ in 0..*b {
254 result.extend(a.clone());
255 }
256 Ok(PythonValue::Tuple(result))
257 }
258 else {
259 Ok(PythonValue::Tuple(Vec::new()))
260 }
261 }
262 _ => Err(PythonError::TypeError("unsupported operand type(s) for *".to_string())),
263 }
264 }
265
266 pub fn div(&self, other: &PythonValue) -> PythonResult<PythonValue> {
268 match (self, other) {
269 (_, PythonValue::Integer(0)) | (_, PythonValue::Float(0.0)) => {
270 Err(PythonError::ZeroDivisionError("division by zero".to_string()))
271 }
272 (PythonValue::Integer(a), PythonValue::Integer(b)) => Ok(PythonValue::Float((*a as f64) / (*b as f64))),
273 (PythonValue::Integer(a), PythonValue::Float(b)) => Ok(PythonValue::Float((*a as f64) / *b)),
274 (PythonValue::Float(a), PythonValue::Integer(b)) => Ok(PythonValue::Float(*a / (*b as f64))),
275 (PythonValue::Float(a), PythonValue::Float(b)) => Ok(PythonValue::Float(*a / *b)),
276 _ => Err(PythonError::TypeError("unsupported operand type(s) for /".to_string())),
277 }
278 }
279
280 pub fn eq(&self, other: &PythonValue) -> bool {
282 self == other
283 }
284
285 pub fn lt(&self, other: &PythonValue) -> PythonResult<bool> {
287 match (self, other) {
288 (PythonValue::Integer(a), PythonValue::Integer(b)) => Ok(a < b),
289 (PythonValue::Integer(a), PythonValue::Float(b)) => Ok((*a as f64) < *b),
290 (PythonValue::Float(a), PythonValue::Integer(b)) => Ok(*a < (*b as f64)),
291 (PythonValue::Float(a), PythonValue::Float(b)) => Ok(a < b),
292 (PythonValue::String(a), PythonValue::String(b)) => Ok(a < b),
293 _ => Err(PythonError::TypeError("unorderable types".to_string())),
294 }
295 }
296
297 pub fn gt(&self, other: &PythonValue) -> PythonResult<bool> {
299 match (self, other) {
300 (PythonValue::Integer(a), PythonValue::Integer(b)) => Ok(a > b),
301 (PythonValue::Integer(a), PythonValue::Float(b)) => Ok((*a as f64) > *b),
302 (PythonValue::Float(a), PythonValue::Integer(b)) => Ok(*a > (*b as f64)),
303 (PythonValue::Float(a), PythonValue::Float(b)) => Ok(a > b),
304 (PythonValue::String(a), PythonValue::String(b)) => Ok(a > b),
305 _ => Err(PythonError::TypeError("unorderable types".to_string())),
306 }
307 }
308}
309
310#[derive(Debug, Clone, PartialEq)]
312pub enum PythonError {
313 MethodNotFound(String),
315 AttributeNotFound(String),
317 LexicalError(String),
319 SyntaxError(String),
321 RuntimeError(String),
323 TypeError(String),
325 ArgumentError(String),
327 NameError(String),
329 IndexError(String),
331 KeyError(String),
333 ZeroDivisionError(String),
335 IOError(String),
337 ImportError(String),
339}
340
341impl std::fmt::Display for PythonError {
342 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
343 match self {
344 PythonError::MethodNotFound(name) => write!(f, "Method not found: {}", name),
345 PythonError::AttributeNotFound(name) => write!(f, "Attribute not found: {}", name),
346 PythonError::LexicalError(msg) => write!(f, "Lexical error: {}", msg),
347 PythonError::SyntaxError(msg) => write!(f, "Syntax error: {}", msg),
348 PythonError::RuntimeError(msg) => write!(f, "Runtime error: {}", msg),
349 PythonError::TypeError(msg) => write!(f, "Type error: {}", msg),
350 PythonError::ArgumentError(msg) => write!(f, "Argument error: {}", msg),
351 PythonError::NameError(msg) => write!(f, "Name error: {}", msg),
352 PythonError::IndexError(msg) => write!(f, "Index error: {}", msg),
353 PythonError::KeyError(msg) => write!(f, "Key error: {}", msg),
354 PythonError::ZeroDivisionError(msg) => write!(f, "ZeroDivisionError: {}", msg),
355 PythonError::IOError(msg) => write!(f, "IO error: {}", msg),
356 PythonError::ImportError(msg) => write!(f, "Import error: {}", msg),
357 }
358 }
359}
360
361impl std::error::Error for PythonError {}
362
363pub type PythonResult<T> = std::result::Result<T, PythonError>;