1use crate::bytecode::ByteCode;
2use regex::Regex;
3use std::cell::RefCell;
4use std::collections::HashMap;
5use std::rc::Rc;
6
7pub type NativeFunction = fn(Vec<Value>) -> Result<Value, Value>;
9
10#[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#[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#[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#[derive(Debug, Clone, PartialEq, Eq, Hash)]
90pub enum DictKey {
91 String(String),
92 Int(i32),
93}
94
95#[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, },
108 DictKeys {
109 keys: Vec<DictKey>,
110 index: usize,
111 },
112 String {
113 chars: Vec<char>,
114 index: usize,
115 },
116}
117
118#[derive(Debug, Clone, PartialEq)]
120pub enum ExceptionType {
121 Exception, RuntimeError, IndexError, KeyError, ValueError, TypeError, ZeroDivisionError, IteratorError, OSError, AttributeError, }
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 pub fn matches(&self, handler: &ExceptionType) -> bool {
168 match handler {
169 ExceptionType::Exception => true, _ => self == handler, }
172 }
173}
174
175#[derive(Debug, Clone)]
177pub struct TracebackFrame {
178 pub function_name: String,
179 pub line_number: usize,
180}
181
182#[derive(Debug, Clone)]
184pub struct ExceptionValue {
185 pub exception_type: ExceptionType,
186 pub message: String,
187 pub traceback: Option<Vec<TracebackFrame>>,
188}
189
190#[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>>), 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>), Generator(Rc<RefCell<GeneratorState>>), AsyncSleep(f64), Exception(ExceptionValue),
212 Module(Rc<RefCell<Module>>),
213 NativeFunction(NativeFunction),
214 BoundMethod(Box<Value>, String), Regex(Rc<Regex>),
216 Match(Rc<MatchObject>),
217 Type(TypeObject),
218}
219
220#[derive(Debug, Clone, Copy, PartialEq, Eq)]
221pub enum TypeObject {
222 Int,
223 Float,
224 Bool,
225 Str,
226 List,
227 Dict,
228 Tuple,
229 NoneType,
230}
231
232impl std::fmt::Debug for Value {
233 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
234 match self {
235 Value::Int(i) => write!(f, "Int({})", i),
236 Value::Float(fl) => write!(f, "Float({})", fl),
237 Value::Bool(b) => write!(f, "Bool({})", b),
238 Value::None => write!(f, "None"),
239 Value::String(s) => write!(f, "String({:?})", s),
240 Value::List(l) => write!(f, "List({:?})", l),
241 Value::Dict(d) => write!(f, "Dict({:?})", d),
242 Value::Tuple(t) => write!(f, "Tuple({:?})", t),
243 Value::Slice { start, stop, step } => {
244 write!(f, "Slice({:?}:{:?}:{:?})", start, stop, step)
245 }
246 Value::Iterator(i) => write!(f, "Iterator({:?})", i),
247 Value::Function(func) => write!(f, "Function({:?})", func),
248 Value::Coroutine(func, _) => write!(f, "Coroutine({:?})", func.name),
249 Value::Generator(gen_rc) => {
250 let gen_state = gen_rc.borrow();
251 write!(
252 f,
253 "Generator({}, finished={})",
254 gen_state.function.name, gen_state.finished
255 )
256 }
257 Value::AsyncSleep(seconds) => write!(f, "AsyncSleep({})", seconds),
258 Value::Exception(e) => write!(f, "Exception({:?})", e),
259 Value::Module(m) => write!(f, "Module({:?})", m),
260 Value::NativeFunction(_) => write!(f, "NativeFunction(<native>)"),
261 Value::BoundMethod(_, method_name) => write!(f, "BoundMethod(<{}>)", method_name),
262 Value::Regex(_) => write!(f, "Regex(<pattern>)"),
263 Value::Match(m) => write!(f, "Match({:?})", m),
264 Value::Type(t) => write!(f, "Type({:?})", t),
265 }
266 }
267}
268
269#[derive(Debug, Clone, PartialEq)]
270pub struct Function {
271 pub name: String,
272 pub params: Vec<String>,
273 pub code: ByteCode,
274 pub is_async: bool,
275 pub is_generator: bool,
276}
277
278#[derive(Debug, Clone)]
280pub struct GeneratorState {
281 pub function: Function,
282 pub locals: Vec<Value>,
283 pub ip: usize,
284 pub stack: Vec<Value>,
285 pub finished: bool,
286}
287
288impl Value {
289 pub fn as_int(&self) -> Option<i32> {
290 match self {
291 Value::Int(i) => Some(*i),
292 _ => None,
293 }
294 }
295
296 pub fn as_float(&self) -> Option<f64> {
297 match self {
298 Value::Float(f) => Some(*f),
299 _ => None,
300 }
301 }
302
303 pub fn as_bool(&self) -> Option<bool> {
304 match self {
305 Value::Bool(b) => Some(*b),
306 _ => None,
307 }
308 }
309
310 pub fn as_string(&self) -> Option<&str> {
311 match self {
312 Value::String(s) => Some(s),
313 _ => None,
314 }
315 }
316
317 pub fn as_list(&self) -> Option<Rc<RefCell<ListValue>>> {
318 match self {
319 Value::List(list) => Some(list.clone()),
320 _ => None,
321 }
322 }
323
324 pub fn as_dict(&self) -> Option<Rc<RefCell<HashMap<DictKey, Value>>>> {
325 match self {
326 Value::Dict(dict) => Some(dict.clone()),
327 _ => None,
328 }
329 }
330
331 pub fn error(exception_type: ExceptionType, message: impl Into<String>) -> Value {
333 Value::Exception(ExceptionValue {
334 exception_type,
335 message: message.into(),
336 traceback: None,
337 })
338 }
339
340 pub fn is_exception(&self) -> bool {
342 matches!(self, Value::Exception(_))
343 }
344
345 pub fn as_exception(&self) -> Option<&ExceptionValue> {
347 match self {
348 Value::Exception(exc) => Some(exc),
349 _ => None,
350 }
351 }
352
353 pub fn is_truthy(&self) -> bool {
354 match self {
355 Value::Bool(b) => *b,
356 Value::Int(i) => *i != 0,
357 Value::Float(f) => *f != 0.0,
358 Value::None => false,
359 Value::String(s) => !s.is_empty(),
360 Value::List(list) => !list.borrow().items.is_empty(),
361 Value::Dict(dict) => !dict.borrow().is_empty(),
362 Value::Tuple(tuple) => !tuple.is_empty(),
363 Value::Slice { .. } => true,
364 Value::Iterator(_) => true,
365 Value::Function(_) => true,
366 Value::Coroutine(_, _) => true,
367 Value::Generator(_) => true,
368 Value::AsyncSleep(_) => true,
369 Value::Exception(_) => true,
370 Value::Module(_) => true,
371 Value::NativeFunction(_) => true,
372 Value::BoundMethod(_, _) => true,
373 Value::Regex(_) => true,
374 Value::Match(_) => true,
375 Value::Type(_) => true,
376 }
377 }
378}
379
380impl PartialEq for Value {
381 fn eq(&self, other: &Self) -> bool {
382 match (self, other) {
383 (Value::Int(a), Value::Int(b)) => a == b,
384 (Value::Float(a), Value::Float(b)) => a == b,
385 (Value::Int(a), Value::Float(b)) => (*a as f64) == *b,
387 (Value::Float(a), Value::Int(b)) => *a == (*b as f64),
388 (Value::Bool(a), Value::Bool(b)) => a == b,
389 (Value::None, Value::None) => true,
390 (Value::String(a), Value::String(b)) => a == b,
391 (Value::List(a), Value::List(b)) => {
392 let a_items = &a.borrow().items;
393 let b_items = &b.borrow().items;
394 a_items == b_items
395 }
396 (Value::Dict(a), Value::Dict(b)) => Rc::ptr_eq(a, b),
397 (Value::Tuple(a), Value::Tuple(b)) => a.as_ref() == b.as_ref(),
398 (
399 Value::Slice {
400 start: s1,
401 stop: st1,
402 step: step1,
403 },
404 Value::Slice {
405 start: s2,
406 stop: st2,
407 step: step2,
408 },
409 ) => s1 == s2 && st1 == st2 && step1 == step2,
410 (Value::Iterator(a), Value::Iterator(b)) => Rc::ptr_eq(a, b),
411 (Value::Function(a), Value::Function(b)) => a == b,
412 (Value::Coroutine(f1, _), Value::Coroutine(f2, _)) => f1 == f2,
413 (Value::Generator(a), Value::Generator(b)) => Rc::ptr_eq(a, b),
414 (Value::AsyncSleep(a), Value::AsyncSleep(b)) => a == b,
415 (Value::Exception(a), Value::Exception(b)) => {
416 a.exception_type == b.exception_type && a.message == b.message
417 }
418 (Value::Module(a), Value::Module(b)) => Rc::ptr_eq(a, b),
419 (Value::NativeFunction(a), Value::NativeFunction(b)) => std::ptr::eq(a, b),
420 (Value::BoundMethod(a1, m1), Value::BoundMethod(a2, m2)) => a1 == a2 && m1 == m2,
421 (Value::Regex(a), Value::Regex(b)) => Rc::ptr_eq(a, b),
422 (Value::Match(a), Value::Match(b)) => Rc::ptr_eq(a, b),
423 (Value::Type(a), Value::Type(b)) => a == b,
424 _ => false,
425 }
426 }
427}