ryna/
object.rs

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