nessa/
object.rs

1use std::{cell::RefCell, fs::File, path::PathBuf};
2
3use crate::{compilation::message_and_exit, context::NessaContext, mut_cell::MutCell, types::{Type, ARR_ID, ARR_IT_ID, BOOL, BOOL_ID, FILE, FILE_ID, FLOAT, FLOAT_ID, INT, INT_ID, STR, STR_ID}, ARR_IT_OF, ARR_OF};
4use malachite::Integer;
5use rclite::Rc;
6use serde::{Deserialize, Serialize};
7
8type DataBlock = Rc<MutCell<ObjectBlock>>;
9
10/*
11                                                  ╒══════════════════╕
12    ============================================= │  IMPLEMENTATION  │ =============================================
13                                                  ╘══════════════════╛
14*/
15
16#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
17pub struct NessaArray {
18    pub elements: Vec<Object>,
19    pub elem_type: Box<Type>
20}
21
22#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
23pub struct NessaTuple {
24    pub elements: Vec<Object>,
25    pub elem_types: Vec<Type>
26}
27
28#[derive(Clone, PartialEq, Debug)]
29pub struct NessaArrayIt {
30    pub pos: usize,
31    pub block: DataBlock,
32    pub it_type: Box<Type>
33}
34
35#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
36pub struct NessaLambda {
37    pub loc: usize,
38    pub captures: Vec<Object>,
39    pub args_type: Box<Type>,
40    pub ret_type: Box<Type>
41}
42
43#[derive(Clone, Debug)]
44pub struct NessaFile {
45    pub path: PathBuf,
46    pub file: Option<Rc<RefCell<File>>>
47}
48
49impl PartialEq for NessaFile {
50    fn eq(&self, other: &Self) -> bool {
51        match (&self.file, &other.file) {
52            (None, None) => self.path == other.path,
53            (Some(a), Some(b)) => self.path == other.path && Rc::ptr_eq(a, b),
54
55            _ => false
56        }
57    }
58}
59
60impl NessaFile {
61    pub fn is_open(&self) -> bool {
62        self.file.is_some()
63    }
64
65    pub fn close(&mut self) -> Result<(), String> {
66        if !self.is_open() {
67            return Err(format!("File at {} is already closed", self.path.to_str().unwrap()));
68        }
69
70        self.file = None;
71
72        Ok(())
73    }
74
75    pub fn open(&mut self, read: bool, write: bool, append: bool) -> Result<(), String> {
76        if self.is_open() {
77            return Err(format!("File at {} is already open", self.path.to_str().unwrap()));
78        }
79
80        let file = std::fs::OpenOptions::new()
81            .create(write || append)
82            .read(read)
83            .write(write)
84            .append(append)
85            .open(&self.path);
86
87        match file {
88            Ok(inner) => {
89                self.file = Some(Rc::new(RefCell::new(inner)));
90                Ok(())
91            },
92
93            Err(_) => Err(format!("Unable to open file file at {}", self.path.to_str().unwrap()))
94        }    
95    }
96
97    pub fn exists(&self) -> Result<bool, String> {
98        Ok(self.path.is_file())
99    }
100
101    pub fn delete(&mut self) -> Result<bool, String> {
102        if !self.is_open() {
103            return Err(format!("File at {} is closed", self.path.to_str().unwrap()));
104        }
105
106        if std::fs::remove_file(&self.path).is_ok() {
107            self.file = None;
108            Ok(true)
109        
110        } else {
111            Ok(false)
112        }
113    }
114}
115
116#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
117pub struct TypeInstance {
118    pub id: usize,
119    pub params: Vec<Type>,
120    pub attributes: Vec<Object>
121}
122
123#[derive(Clone, PartialEq, Debug, Default, Serialize, Deserialize)]
124pub enum ObjectBlock {
125    #[default]
126    NoValue, //  Empty is a type, this represents no value at all
127
128    Empty,
129    Int(malachite::Integer),
130    Float(f64),
131    Str(String),
132    Bool(bool),
133
134    Tuple(NessaTuple),
135    Array(NessaArray),
136
137    #[serde(skip)]
138    ArrayIter(NessaArrayIt),
139
140    Lambda(NessaLambda),
141
142    #[serde(skip)]
143    File(NessaFile),
144
145    Instance(TypeInstance),
146
147    #[serde(skip)]
148    Ref(DataBlock),
149    #[serde(skip)]
150    Mut(DataBlock),
151}
152
153impl Eq for ObjectBlock {}
154
155impl ObjectBlock {
156    #[inline(always)]
157    pub fn to_obj(self) -> Object {
158        Object { inner: Rc::new(MutCell::new(self)) }
159    } 
160
161    pub fn get_type_id(&self) -> usize {
162        match self {
163            ObjectBlock::NoValue => message_and_exit("Accessing moved object".into()),
164            ObjectBlock::Empty => 0,
165            ObjectBlock::Int(_) => INT_ID,
166            ObjectBlock::Float(_) => FLOAT_ID,
167            ObjectBlock::Str(_) => STR_ID,
168            ObjectBlock::Bool(_) => BOOL_ID,
169            ObjectBlock::Tuple(_) => 0,
170            ObjectBlock::Array(_) => ARR_ID,
171            ObjectBlock::ArrayIter(_) => ARR_IT_ID,
172            ObjectBlock::Lambda(_) => 0,
173            ObjectBlock::File(_) => FILE_ID,
174            ObjectBlock::Instance(i) => i.id,
175            ObjectBlock::Ref(_) => 0,
176            ObjectBlock::Mut(_) => 0,
177        }
178    }
179
180    pub fn get_type(&self) -> Type {
181        return match self {
182            ObjectBlock::NoValue => message_and_exit("Accessing moved object".into()),
183            ObjectBlock::Empty => Type::Empty,
184            ObjectBlock::Int(_) => INT,
185            ObjectBlock::Float(_) => FLOAT,
186            ObjectBlock::Str(_) => STR,
187            ObjectBlock::Bool(_) => BOOL,
188            ObjectBlock::Tuple(t) => Type::And(t.elem_types.clone()),
189            ObjectBlock::Array(a) => ARR_OF!(*a.elem_type.clone()),
190            ObjectBlock::ArrayIter(i) => ARR_IT_OF!(*i.it_type.clone()),
191            ObjectBlock::Lambda(l) => Type::Function(l.args_type.clone(), l.ret_type.clone()),
192            ObjectBlock::File(_) => FILE,
193            ObjectBlock::Instance(i) => if i.params.is_empty() { Type::Basic(i.id) } else { Type::Template(i.id, i.params.clone()) },
194            ObjectBlock::Ref(r) => Type::Ref(Box::new(r.borrow().get_type())),
195            ObjectBlock::Mut(r) => Type::MutRef(Box::new(r.borrow().get_type())),
196        };
197    }
198
199    pub fn is_moved(&self) -> bool {
200        matches!(self, ObjectBlock::NoValue)
201    }
202
203    pub fn get_inner<T>(&self) -> &T where ObjectBlock: Get<T> {
204        return Get::<T>::get(self);
205    }
206
207    pub fn mut_inner<T>(&mut self) -> &mut T where ObjectBlock: GetMut<T> {
208        return GetMut::<T>::get(self);
209    }
210
211    pub fn dereference(&self) -> &DataBlock {
212        if let ObjectBlock::Ref(n) | ObjectBlock::Mut(n) = self {
213            return n;
214        }
215
216        unreachable!();
217    }
218
219    pub fn assign_ref(&mut self, other: ObjectBlock, ctx: &NessaContext) -> Result<(), String> {
220        self.dereference().borrow_mut().assign(other, ctx)
221    }
222
223    pub fn assign(&mut self, other: ObjectBlock, ctx: &NessaContext) -> Result<(), String> {
224        use ObjectBlock::*;
225
226        match (self, other) {
227            (Int(a), Int(b)) => *a = b,
228            (Float(a), Float(b)) => *a = b,
229            (Str(a), Str(b)) => *a = b,
230            (Bool(a), Bool(b)) => *a = b,
231            (Array(a), Array(b)) if a.elem_type == b.elem_type => *a = b,
232            (ArrayIter(a), ArrayIter(b)) if a.it_type == b.it_type => *a = b,
233            (Lambda(a), Lambda(b)) if a.args_type == b.args_type && a.ret_type == b.ret_type => *a = b,
234            (Instance(a), Instance(b)) if a.id == b.id && a.params == b.params => *a = b,
235            (Tuple(a), Tuple(b)) if a.elem_types == b.elem_types => *a = b,
236
237            (a, b) => return Err(format!(
238                "Unable to assign value of type {} to block of type {}", 
239                b.get_type().get_name(ctx),
240                a.get_type().get_name(ctx)
241            ))
242        };
243
244        Ok(())
245    }
246
247    pub fn deep_clone(&self) -> Self {
248        return match self {
249            ObjectBlock::NoValue => message_and_exit("Accessing moved object".into()),
250
251            ObjectBlock::Empty => ObjectBlock::Empty,
252            ObjectBlock::Int(n) => ObjectBlock::Int(n.clone()),
253            ObjectBlock::Float(n) => ObjectBlock::Float(*n),
254            ObjectBlock::Str(s) => ObjectBlock::Str(s.clone()),
255            ObjectBlock::Bool(b) => ObjectBlock::Bool(*b),
256            ObjectBlock::Tuple(t) => ObjectBlock::Tuple(NessaTuple { 
257                elements: t.elements.iter().map(Object::deep_clone).collect(), 
258                elem_types: t.elem_types.clone()
259            }),
260            ObjectBlock::Array(a) => ObjectBlock::Array(NessaArray { 
261                elements: a.elements.iter().map(Object::deep_clone).collect(), 
262                elem_type: a.elem_type.clone()
263            }),
264            ObjectBlock::ArrayIter(i) => ObjectBlock::ArrayIter(NessaArrayIt { 
265                pos: i.pos, 
266                block: i.block.clone(), 
267                it_type: i.it_type.clone() 
268            }),
269            ObjectBlock::Lambda(l) => ObjectBlock::Lambda(NessaLambda { 
270                loc: l.loc, 
271                captures: l.captures.iter().map(Object::deep_clone).collect(),
272                args_type: l.args_type.clone(), 
273                ret_type: l.ret_type.clone() 
274            }),
275            ObjectBlock::File(f) => ObjectBlock::File(f.clone()),
276            ObjectBlock::Instance(i) => ObjectBlock::Instance(TypeInstance {
277                id: i.id, 
278                params: i.params.clone(), 
279                attributes: i.attributes.iter().map(Object::deep_clone).collect()
280            }),
281            ObjectBlock::Ref(r) => ObjectBlock::Ref(r.clone()),
282            ObjectBlock::Mut(r) => ObjectBlock::Mut(r.clone()),
283        }
284    }
285}
286
287#[derive(Clone, PartialEq, Eq, Debug)]
288pub struct Object {
289    pub inner: DataBlock
290}
291
292impl Serialize for Object {
293    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
294    where
295        S: serde::Serializer {
296        self.inner.borrow().serialize(serializer)
297    }
298}
299
300impl<'de> Deserialize<'de> for Object {
301    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
302    where
303        D: serde::Deserializer<'de> {
304        let inner = ObjectBlock::deserialize(deserializer)?;
305        Ok(inner.to_obj())
306    }
307}
308
309impl Object {
310    pub fn new<T: NessaData>(data: T) -> Self {
311        data.data().to_obj()
312    }
313
314    pub fn get_ptr(&self) -> *mut ObjectBlock {
315        (*self.inner).as_ptr()
316    }
317
318    pub fn arr(elements: Vec<Object>, elem_type: Type) -> Self {
319        ObjectBlock::Array(NessaArray { elements, elem_type: Box::new(elem_type) }).to_obj()
320    }
321
322    pub fn arr_it(it_type: Type, block: DataBlock, pos: usize) -> Self {
323        ObjectBlock::ArrayIter(NessaArrayIt { pos, block, it_type: Box::new(it_type) }).to_obj()
324    }
325
326    pub fn lambda(loc: usize, captures: Vec<Object>, args_type: Type, ret_type: Type) -> Self {
327        ObjectBlock::Lambda(NessaLambda { loc, captures, args_type: Box::new(args_type), ret_type: Box::new(ret_type) }).to_obj()
328    }
329
330    pub fn tuple(elements: Vec<Object>, elem_types: Vec<Type>) -> Self {
331        ObjectBlock::Tuple(NessaTuple { elements, elem_types }).to_obj()
332    }
333
334    pub fn file(path: PathBuf) -> Self {
335        ObjectBlock::File(NessaFile { path, file: None }).to_obj()
336    }
337
338    pub fn instance(attributes: Vec<Object>, params: Vec<Type>, id: usize) -> Self {
339        ObjectBlock::Instance(TypeInstance { params, attributes, id }).to_obj()
340    }
341
342    pub fn get<T>(&self) -> &T where ObjectBlock: Get<T> {
343        Get::<T>::get(self.inner.borrow())
344    }
345
346    #[allow(clippy::should_implement_trait)]
347    pub fn deref<T>(&self) -> &mut T where ObjectBlock: Deref<T> + GetMut<T> {
348        Deref::<T>::deref(self.inner.borrow())
349    }
350
351    pub fn ref_count(&self) -> usize {
352        Rc::strong_count(&self.inner)
353    }
354
355    pub fn is_moved(&self) -> bool {
356        return self.inner.borrow().is_moved();
357    }
358
359    /*
360        Moves self contents to the returned value and leaves Moved
361    */
362    pub fn move_contents(&self) -> Object {
363        let res = ObjectBlock::default().to_obj();
364
365        match &mut *self.inner.borrow_mut() {
366            ObjectBlock::Mut(i) => std::mem::swap(&mut *i.borrow_mut(), &mut *res.inner.borrow_mut()),
367            _ => unreachable!()
368        };
369
370        res
371    }
372    
373    pub fn move_contents_if_ref(&self) -> Object {
374        let res = ObjectBlock::default().to_obj();
375
376        match &mut *self.inner.borrow_mut() {
377            ObjectBlock::Mut(i) => std::mem::swap(&mut *i.borrow_mut(), &mut *res.inner.borrow_mut()),
378            i => std::mem::swap(i, &mut *res.inner.borrow_mut())
379        };
380
381        res
382    }
383
384    pub fn swap_contents(&self, other: &Object) {
385        match (&mut *self.inner.borrow_mut(), &mut *other.inner.borrow_mut()) {
386            (ObjectBlock::Mut(a), ObjectBlock::Mut(b)) => std::mem::swap(&mut *a.borrow_mut(), &mut *b.borrow_mut()),
387            _ => unreachable!()
388        };
389    }
390
391    pub fn drop_contents(&self) {
392        match &mut *self.inner.borrow_mut() {
393            ObjectBlock::Mut(i) => std::mem::take(&mut *i.borrow_mut()),
394            _ => unreachable!()
395        };
396    }
397    
398    pub fn assign(&self, other_obj: Object, ctx: &NessaContext) -> Result<(), String> {
399        match Rc::try_unwrap(other_obj.inner) {
400            Ok(inner) => self.inner.borrow_mut().assign_ref(inner.take(), ctx),
401            Err(inner) => self.inner.borrow_mut().assign_ref(inner.borrow().clone(), ctx)
402        }
403    }
404    
405    pub fn assign_direct(&self, other_obj: Object, ctx: &NessaContext) -> Result<(), String> {
406        match Rc::try_unwrap(other_obj.inner) {
407            Ok(inner) => self.inner.borrow_mut().assign(inner.take(), ctx),
408            Err(inner) => self.inner.borrow_mut().assign(inner.borrow().clone(), ctx)
409        }
410    }
411
412    pub fn from_inner(inner: DataBlock) -> Self {
413        Object { inner }
414    }
415
416    pub fn no_value() -> Object {
417        ObjectBlock::NoValue.to_obj()
418    }
419
420    pub fn empty() -> Object {
421        ObjectBlock::Empty.to_obj()
422    }
423
424    pub fn get_ref(&self) -> Object {
425        return match self.inner.borrow() {
426            ObjectBlock::Ref(i) |
427            ObjectBlock::Mut(i) => ObjectBlock::Ref(i.clone()).to_obj(),
428
429            _ => ObjectBlock::Ref(self.inner.clone()).to_obj()
430        }
431    }
432
433    pub fn get_mut(&self) -> Object {
434        return match self.inner.borrow() {
435            ObjectBlock::Ref(i) |
436            ObjectBlock::Mut(i) => ObjectBlock::Mut(i.clone()).to_obj(),
437
438            _ => ObjectBlock::Mut(self.inner.clone()).to_obj()
439        }
440    }
441
442    pub fn get_ref_nostack(&self) -> Object {
443        ObjectBlock::Ref(self.inner.clone()).to_obj()
444    }
445
446    pub fn get_mut_nostack(&self) -> Object {
447        ObjectBlock::Mut(self.inner.clone()).to_obj()
448    }
449
450    pub fn to_debug_string(&self) -> String {
451        format!("{:?}", self.inner.borrow())
452    }
453
454    pub fn deref_if_ref(&self) -> Object {
455        return match self.inner.borrow() {
456            ObjectBlock::Ref(i) |
457            ObjectBlock::Mut(i) => Object::from_inner(i.clone()),
458
459            _ => self.clone()
460        }
461    }
462
463    pub fn deref_deep_clone(&self) -> Object {
464        return match self.inner.borrow() {
465            ObjectBlock::Ref(i) |
466            ObjectBlock::Mut(i) => i.borrow().deep_clone().to_obj(),
467
468            obj => obj.deep_clone().to_obj()
469        }
470    }
471
472    pub fn deep_clone(&self) -> Object {
473        self.inner.borrow().deep_clone().to_obj()
474    }
475
476    pub fn get_type_id(&self) -> usize {
477        return self.inner.borrow().get_type_id();
478    }
479
480    pub fn get_type(&self) -> Type {
481        return self.inner.borrow().get_type();
482    }
483
484    pub fn deref_obj(&self) -> Object {
485        return match self.inner.borrow() {
486            ObjectBlock::Ref(r) | ObjectBlock::Mut(r) => Object::from_inner(r.clone()),
487            _ => unreachable!()
488        };
489    }
490}
491
492pub trait NessaData {
493    fn data(self) -> ObjectBlock;
494}
495
496pub trait Get<T> {
497    fn get(&self) -> &T;
498}
499
500pub trait GetMut<T> {
501    fn get(&mut self) -> &mut T;
502}
503
504pub trait Deref<T> {
505    #[allow(clippy::mut_from_ref)]
506    fn deref(&self) -> &mut T;
507}
508
509macro_rules! impl_nessa_data {
510    ($t: ty, $v: tt) => {
511        impl NessaData for $t {
512            #[inline(always)]
513            fn data(self) -> ObjectBlock {
514                return ObjectBlock::$v(self)
515            }
516        }
517
518        impl Get<$t> for ObjectBlock {
519            #[inline(always)]
520            fn get(&self) -> &$t {
521                if let ObjectBlock::$v(n) = self {
522                    return n;
523                }
524        
525                unreachable!("Unable to get {:?}", self);    
526            }
527        }
528
529        impl GetMut<$t> for ObjectBlock {
530            #[inline(always)]
531            fn get(&mut self) -> &mut $t {
532                if let ObjectBlock::$v(n) = self {
533                    return n;
534                }
535        
536                unreachable!("Unable to get mut {:?}", self);    
537            }
538        }
539
540        impl Deref<$t> for ObjectBlock {
541            #[inline(always)]
542            fn deref(&self) -> &mut $t {
543                return GetMut::<$t>::get(self.dereference().borrow_mut());
544            }
545        }
546    };
547}
548
549impl_nessa_data!(Integer, Int);
550impl_nessa_data!(f64, Float);
551impl_nessa_data!(String, Str);
552impl_nessa_data!(bool, Bool);
553impl_nessa_data!(TypeInstance, Instance);
554impl_nessa_data!(NessaArray, Array);
555impl_nessa_data!(NessaTuple, Tuple);
556impl_nessa_data!(NessaLambda, Lambda);
557impl_nessa_data!(NessaArrayIt, ArrayIter);
558impl_nessa_data!(NessaFile, File);
559
560/*
561                                                  ╒═════════╕
562    ============================================= │  TESTS  │ =============================================
563                                                  ╘═════════╛
564*/
565
566#[cfg(test)]
567mod tests {
568    use crate::context::standard_ctx;
569    use malachite::Integer;
570    use crate::object::*;
571
572    #[test]
573    fn object_construction() {
574        let number = Object::new(Integer::from(10));
575        
576        assert_eq!(*number.get::<Integer>(), Integer::from(10));
577
578        let string = Object::new(String::from("Test"));
579        
580        assert_eq!(*string.get::<String>(), "Test".to_string());
581
582        assert_ne!(number.get_type_id(), string.get_type_id());
583    }
584
585    #[test]
586    fn references() {
587        let ctx = standard_ctx();
588
589        let number = Object::new(Integer::from(10));
590        
591        assert_eq!(*number.get::<Integer>(), Integer::from(10));
592
593        let reference = number.get_mut();
594        let ref_of_ref = reference.get_ref();
595
596        assert_eq!(*reference.deref::<Integer>(), Integer::from(10));
597        assert_eq!(*ref_of_ref.deref::<Integer>(), Integer::from(10));
598
599        assert_ne!(number.get_ptr(), reference.get_ptr());
600        assert_ne!(number.get_ptr(), ref_of_ref.get_ptr());
601        assert_ne!(reference.get_ptr(), ref_of_ref.get_ptr());
602        assert_eq!(number.get_ptr(), (**reference.inner.borrow().dereference()).as_ptr());
603        assert_eq!(number.get_ptr(), (**ref_of_ref.inner.borrow().dereference()).as_ptr());
604
605        {
606            *reference.deref::<Integer>() += Integer::from(5);    
607        }
608
609        assert_eq!(*number.get::<Integer>(), Integer::from(15));
610        assert_eq!(*reference.deref::<Integer>(), Integer::from(15));
611        assert_eq!(*ref_of_ref.deref::<Integer>(), Integer::from(15));
612
613        reference.assign(ObjectBlock::Int(Integer::from(20)).to_obj(), &ctx).unwrap();
614
615        assert_eq!(*number.get::<Integer>(), Integer::from(20));
616        assert_eq!(*reference.deref::<Integer>(), Integer::from(20));
617        assert_eq!(*ref_of_ref.deref::<Integer>(), Integer::from(20));
618    }
619
620    #[test]
621    fn value_moving() {
622        let number = Object::new(Integer::from(10));
623        
624        assert_eq!(*number.get::<Integer>(), Integer::from(10));
625
626        let reference = number.get_mut();
627        let ref_of_ref = reference.get_mut();
628
629        assert_ne!(number.get_ptr(), reference.get_ptr());
630        assert_ne!(number.get_ptr(), ref_of_ref.get_ptr());
631        assert_ne!(reference.get_ptr(), ref_of_ref.get_ptr());
632        assert_eq!(number.get_ptr(), (**reference.inner.borrow().dereference()).as_ptr());
633        assert_eq!(number.get_ptr(), (**ref_of_ref.inner.borrow().dereference()).as_ptr());
634
635        assert_eq!(number.ref_count(), 3);
636
637        let number_2 = reference.move_contents();
638
639        assert!(number.is_moved());
640        assert!(reference.deref_obj().is_moved());
641        assert!(ref_of_ref.deref_obj().is_moved());
642        assert_eq!(number.ref_count(), 3);
643
644        assert!(!number_2.is_moved());
645        assert_eq!(number_2.ref_count(), 1);
646        assert_eq!(*number_2.get::<Integer>(), Integer::from(10));
647    }
648}