Skip to main content

quickpython/
value.rs

1use crate::bytecode::ByteCode;
2use regex::Regex;
3use std::cell::RefCell;
4use std::collections::HashMap;
5use std::rc::Rc;
6
7/// Native function type - Rust functions callable from Python
8pub type NativeFunction = fn(Vec<Value>) -> Result<Value, Value>;
9
10/// Module structure
11#[derive(Clone)]
12pub struct Module {
13    pub name: String,
14    pub attributes: HashMap<String, Value>,
15}
16
17impl Module {
18    pub fn new(name: &str) -> Self {
19        Module {
20            name: name.to_string(),
21            attributes: HashMap::new(),
22        }
23    }
24
25    pub fn add_function(&mut self, name: &str, func: NativeFunction) {
26        self.attributes
27            .insert(name.to_string(), Value::NativeFunction(func));
28    }
29
30    pub fn get_attribute(&self, name: &str) -> Option<Value> {
31        self.attributes.get(name).cloned()
32    }
33}
34
35impl std::fmt::Debug for Module {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        f.debug_struct("Module")
38            .field("name", &self.name)
39            .field("attributes", &self.attributes.keys().collect::<Vec<_>>())
40            .finish()
41    }
42}
43
44/// Match object for regex matches
45#[derive(Debug, Clone)]
46pub struct MatchObject {
47    pub text: String,
48    pub start: usize,
49    pub end: usize,
50    pub groups: Vec<Option<String>>,
51}
52
53impl MatchObject {
54    pub fn new(text: String, start: usize, end: usize, groups: Vec<Option<String>>) -> Self {
55        MatchObject {
56            text,
57            start,
58            end,
59            groups,
60        }
61    }
62}
63
64/// List value with version tracking for iterator modification detection
65#[derive(Debug, Clone)]
66pub struct ListValue {
67    pub items: Vec<Value>,
68    pub version: usize,
69}
70
71impl ListValue {
72    pub fn new() -> Self {
73        ListValue {
74            items: Vec::new(),
75            version: 0,
76        }
77    }
78
79    pub fn with_items(items: Vec<Value>) -> Self {
80        ListValue { items, version: 0 }
81    }
82
83    pub fn increment_version(&mut self) {
84        self.version = self.version.wrapping_add(1);
85    }
86}
87
88/// Dictionary key type - only String and Int are supported
89#[derive(Debug, Clone, PartialEq, Eq, Hash)]
90pub enum DictKey {
91    String(String),
92    Int(i32),
93}
94
95/// Iterator state for different types
96#[derive(Debug, Clone)]
97pub enum IteratorState {
98    Range {
99        current: i32,
100        stop: i32,
101        step: i32,
102    },
103    List {
104        list: Rc<RefCell<ListValue>>,
105        index: usize,
106        version: usize, // Version at iterator creation time
107    },
108    DictKeys {
109        keys: Vec<DictKey>,
110        index: usize,
111    },
112    String {
113        chars: Vec<char>,
114        index: usize,
115    },
116}
117
118/// Exception type enumeration
119#[derive(Debug, Clone, PartialEq)]
120pub enum ExceptionType {
121    Exception,         // 基础异常
122    RuntimeError,      // 运行时错误
123    IndexError,        // 索引越界
124    KeyError,          // 键不存在
125    ValueError,        // 值错误
126    TypeError,         // 类型错误
127    ZeroDivisionError, // 除零错误
128    IteratorError,     // 迭代器错误(自定义)
129    OSError,           // 操作系统错误
130    AttributeError,    // 属性错误
131}
132
133impl ExceptionType {
134    pub fn as_i32(&self) -> i32 {
135        match self {
136            ExceptionType::Exception => 0,
137            ExceptionType::RuntimeError => 1,
138            ExceptionType::IndexError => 2,
139            ExceptionType::KeyError => 3,
140            ExceptionType::ValueError => 4,
141            ExceptionType::TypeError => 5,
142            ExceptionType::ZeroDivisionError => 6,
143            ExceptionType::IteratorError => 7,
144            ExceptionType::OSError => 8,
145            ExceptionType::AttributeError => 9,
146        }
147    }
148
149    pub fn from_i32(value: i32) -> Option<Self> {
150        match value {
151            0 => Some(ExceptionType::Exception),
152            1 => Some(ExceptionType::RuntimeError),
153            2 => Some(ExceptionType::IndexError),
154            3 => Some(ExceptionType::KeyError),
155            4 => Some(ExceptionType::ValueError),
156            5 => Some(ExceptionType::TypeError),
157            6 => Some(ExceptionType::ZeroDivisionError),
158            7 => Some(ExceptionType::IteratorError),
159            8 => Some(ExceptionType::OSError),
160            9 => Some(ExceptionType::AttributeError),
161            _ => None,
162        }
163    }
164
165    /// Check if this exception type matches the handler type
166    /// Exception matches all types (it's the base class)
167    pub fn matches(&self, handler: &ExceptionType) -> bool {
168        match handler {
169            ExceptionType::Exception => true, // Exception catches everything
170            _ => self == handler,             // Otherwise exact match
171        }
172    }
173}
174
175/// Traceback frame for exception
176#[derive(Debug, Clone)]
177pub struct TracebackFrame {
178    pub function_name: String,
179    pub line_number: usize,
180}
181
182/// Exception value structure
183#[derive(Debug, Clone)]
184pub struct ExceptionValue {
185    pub exception_type: ExceptionType,
186    pub message: String,
187    pub traceback: Option<Vec<TracebackFrame>>,
188}
189
190/// Value type for QuickPython runtime
191#[derive(Clone)]
192pub enum Value {
193    Int(i32),
194    Float(f64),
195    Bool(bool),
196    None,
197    String(String),
198    List(Rc<RefCell<ListValue>>),
199    Dict(Rc<RefCell<HashMap<DictKey, Value>>>),
200    Tuple(Rc<Vec<Value>>), // Immutable sequence
201    Slice {
202        start: Option<i32>,
203        stop: Option<i32>,
204        step: Option<i32>,
205    },
206    Iterator(Rc<RefCell<IteratorState>>),
207    Function(Function),
208    Coroutine(Function, Vec<Value>), // (async function, captured args)
209    AsyncSleep(f64),                 // Async sleep operation (seconds)
210    Exception(ExceptionValue),
211    Module(Rc<RefCell<Module>>),
212    NativeFunction(NativeFunction),
213    BoundMethod(Box<Value>, String), // (receiver, method_name)
214    Regex(Rc<Regex>),
215    Match(Rc<MatchObject>),
216    Type(TypeObject),
217}
218
219#[derive(Debug, Clone, Copy, PartialEq, Eq)]
220pub enum TypeObject {
221    Int,
222    Float,
223    Bool,
224    Str,
225    List,
226    Dict,
227    Tuple,
228    NoneType,
229}
230
231impl std::fmt::Debug for Value {
232    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
233        match self {
234            Value::Int(i) => write!(f, "Int({})", i),
235            Value::Float(fl) => write!(f, "Float({})", fl),
236            Value::Bool(b) => write!(f, "Bool({})", b),
237            Value::None => write!(f, "None"),
238            Value::String(s) => write!(f, "String({:?})", s),
239            Value::List(l) => write!(f, "List({:?})", l),
240            Value::Dict(d) => write!(f, "Dict({:?})", d),
241            Value::Tuple(t) => write!(f, "Tuple({:?})", t),
242            Value::Slice { start, stop, step } => {
243                write!(f, "Slice({:?}:{:?}:{:?})", start, stop, step)
244            }
245            Value::Iterator(i) => write!(f, "Iterator({:?})", i),
246            Value::Function(func) => write!(f, "Function({:?})", func),
247            Value::Coroutine(func, _) => write!(f, "Coroutine({:?})", func.name),
248            Value::AsyncSleep(seconds) => write!(f, "AsyncSleep({})", seconds),
249            Value::Exception(e) => write!(f, "Exception({:?})", e),
250            Value::Module(m) => write!(f, "Module({:?})", m),
251            Value::NativeFunction(_) => write!(f, "NativeFunction(<native>)"),
252            Value::BoundMethod(_, method_name) => write!(f, "BoundMethod(<{}>)", method_name),
253            Value::Regex(_) => write!(f, "Regex(<pattern>)"),
254            Value::Match(m) => write!(f, "Match({:?})", m),
255            Value::Type(t) => write!(f, "Type({:?})", t),
256        }
257    }
258}
259
260#[derive(Debug, Clone, PartialEq)]
261pub struct Function {
262    pub name: String,
263    pub params: Vec<String>,
264    pub code: ByteCode,
265    pub is_async: bool,
266}
267
268impl Value {
269    pub fn as_int(&self) -> Option<i32> {
270        match self {
271            Value::Int(i) => Some(*i),
272            _ => None,
273        }
274    }
275
276    pub fn as_float(&self) -> Option<f64> {
277        match self {
278            Value::Float(f) => Some(*f),
279            _ => None,
280        }
281    }
282
283    pub fn as_bool(&self) -> Option<bool> {
284        match self {
285            Value::Bool(b) => Some(*b),
286            _ => None,
287        }
288    }
289
290    pub fn as_string(&self) -> Option<&str> {
291        match self {
292            Value::String(s) => Some(s),
293            _ => None,
294        }
295    }
296
297    pub fn as_list(&self) -> Option<Rc<RefCell<ListValue>>> {
298        match self {
299            Value::List(list) => Some(list.clone()),
300            _ => None,
301        }
302    }
303
304    pub fn as_dict(&self) -> Option<Rc<RefCell<HashMap<DictKey, Value>>>> {
305        match self {
306            Value::Dict(dict) => Some(dict.clone()),
307            _ => None,
308        }
309    }
310
311    /// Create an exception value
312    pub fn error(exception_type: ExceptionType, message: impl Into<String>) -> Value {
313        Value::Exception(ExceptionValue {
314            exception_type,
315            message: message.into(),
316            traceback: None,
317        })
318    }
319
320    /// Check if value is an exception
321    pub fn is_exception(&self) -> bool {
322        matches!(self, Value::Exception(_))
323    }
324
325    /// Get exception value
326    pub fn as_exception(&self) -> Option<&ExceptionValue> {
327        match self {
328            Value::Exception(exc) => Some(exc),
329            _ => None,
330        }
331    }
332
333    pub fn is_truthy(&self) -> bool {
334        match self {
335            Value::Bool(b) => *b,
336            Value::Int(i) => *i != 0,
337            Value::Float(f) => *f != 0.0,
338            Value::None => false,
339            Value::String(s) => !s.is_empty(),
340            Value::List(list) => !list.borrow().items.is_empty(),
341            Value::Dict(dict) => !dict.borrow().is_empty(),
342            Value::Tuple(tuple) => !tuple.is_empty(),
343            Value::Slice { .. } => true,
344            Value::Iterator(_) => true,
345            Value::Function(_) => true,
346            Value::Coroutine(_, _) => true,
347            Value::AsyncSleep(_) => true,
348            Value::Exception(_) => true,
349            Value::Module(_) => true,
350            Value::NativeFunction(_) => true,
351            Value::BoundMethod(_, _) => true,
352            Value::Regex(_) => true,
353            Value::Match(_) => true,
354            Value::Type(_) => true,
355        }
356    }
357}
358
359impl PartialEq for Value {
360    fn eq(&self, other: &Self) -> bool {
361        match (self, other) {
362            (Value::Int(a), Value::Int(b)) => a == b,
363            (Value::Float(a), Value::Float(b)) => a == b,
364            (Value::Bool(a), Value::Bool(b)) => a == b,
365            (Value::None, Value::None) => true,
366            (Value::String(a), Value::String(b)) => a == b,
367            (Value::List(a), Value::List(b)) => {
368                let a_items = &a.borrow().items;
369                let b_items = &b.borrow().items;
370                a_items == b_items
371            }
372            (Value::Dict(a), Value::Dict(b)) => Rc::ptr_eq(a, b),
373            (Value::Tuple(a), Value::Tuple(b)) => a.as_ref() == b.as_ref(),
374            (
375                Value::Slice {
376                    start: s1,
377                    stop: st1,
378                    step: step1,
379                },
380                Value::Slice {
381                    start: s2,
382                    stop: st2,
383                    step: step2,
384                },
385            ) => s1 == s2 && st1 == st2 && step1 == step2,
386            (Value::Iterator(a), Value::Iterator(b)) => Rc::ptr_eq(a, b),
387            (Value::Function(a), Value::Function(b)) => a == b,
388            (Value::Coroutine(f1, _), Value::Coroutine(f2, _)) => f1 == f2,
389            (Value::AsyncSleep(a), Value::AsyncSleep(b)) => a == b,
390            (Value::Exception(a), Value::Exception(b)) => {
391                a.exception_type == b.exception_type && a.message == b.message
392            }
393            (Value::Module(a), Value::Module(b)) => Rc::ptr_eq(a, b),
394            (Value::NativeFunction(a), Value::NativeFunction(b)) => std::ptr::eq(a, b),
395            (Value::BoundMethod(a1, m1), Value::BoundMethod(a2, m2)) => a1 == a2 && m1 == m2,
396            (Value::Regex(a), Value::Regex(b)) => Rc::ptr_eq(a, b),
397            (Value::Match(a), Value::Match(b)) => Rc::ptr_eq(a, b),
398            (Value::Type(a), Value::Type(b)) => a == b,
399            _ => false,
400        }
401    }
402}