smodel/
lib.rs

1use std::{cell::RefCell, rc::{Rc, Weak}};
2use std::fmt::Debug;
3
4pub mod util;
5
6pub use smodel_proc::smodel;
7
8pub struct Arena<T> {
9    data: RefCell<Vec<Rc<T>>>,
10}
11
12impl<T> Arena<T> {
13    pub fn new() -> Self {
14        Self {
15            data: RefCell::new(vec![]),
16        }
17    }
18
19    pub fn allocate(&self, value: T) -> Weak<T> {
20        let obj = Rc::new(value);
21        self.data.borrow_mut().push(obj.clone());
22        Rc::downgrade(&obj)
23    }
24}
25
26#[derive(Debug)]
27pub enum SModelError {
28    Contravariant,
29}
30
31#[cfg(test)]
32mod test {
33    #[test]
34    fn test() {
35        use crate::smodel;
36
37        smodel! {
38            mod smodel = crate;
39
40            type Arena = Arena;
41        
42            /// My unified data type.
43            struct Thingy {
44                pub fn Thingy() {
45                    super();
46                }
47        
48                /// Empty, Foo, FooBar or FooQux
49                pub fn name(&self) -> String {
50                    "".into()
51                }
52
53                pub fn base_example(&self) -> String {
54                    "from base".into()
55                }
56
57                pub fn x(&self) -> f64 {
58                    0.0
59                }
60            }
61        
62            struct Foo: Thingy {
63                pub fn Foo() {
64                    super();
65                }
66
67                #[inheritdoc]
68                pub override fn name(&self) -> String {
69                    "Foo".into()
70                }
71            }
72        
73            struct FooBar: Foo {
74                pub fn FooBar() {
75                    super();
76                }
77
78                #[inheritdoc]
79                pub override fn name(&self) -> String {
80                    "FooBar".into()
81                }
82
83                pub override fn base_example(&self) -> String {
84                    format!("from bar; {}", super.base_example())
85                }
86            }
87            
88            struct FooBarBar: FooBar {
89                let m_x: f64 = 0.0;
90                let ref m_y: String = "".into();
91
92                pub fn FooBarBar(x: f64, y: &str) {
93                    super();
94                    self.set_m_x(x);
95                    self.set_m_y(y.into());
96                }
97
98                #[inheritdoc]
99                pub override fn name(&self) -> String {
100                    "FooBarBar".into()
101                }
102
103                pub override fn x(&self) -> f64 {
104                    self.m_x()
105                }
106
107                pub override fn base_example(&self) -> String {
108                    format!("from {}; {}", self.m_y(), super.base_example())
109                }
110            }
111        
112            struct FooQux: Foo {
113                pub fn FooQux() {
114                    super();
115                }
116
117                #[inheritdoc]
118                pub override fn name(&self) -> String {
119                    "FooQux".into()
120                }
121            }
122        }
123
124        let arena = Arena::new();
125
126        let symbol = Foo::new(&arena);
127        let base_symbol: Thingy = symbol.into();
128        assert_eq!("Foo", base_symbol.name());
129        assert_eq!(true, base_symbol.is::<Foo>());
130        assert_eq!(false, base_symbol.is::<FooBar>());
131        assert_eq!(false, base_symbol.is::<FooQux>());
132        assert_eq!("from base", base_symbol.base_example());
133        assert_eq!(0.0, base_symbol.x());
134
135        let symbol = FooBar::new(&arena);
136        let base_symbol: Thingy = symbol.into();
137        assert_eq!("FooBar", base_symbol.name());
138        assert_eq!(true, base_symbol.is::<Foo>());
139        assert_eq!(true, base_symbol.is::<FooBar>());
140        assert_eq!(false, base_symbol.is::<FooBarBar>());
141        assert_eq!(false, base_symbol.is::<FooQux>());
142        assert_eq!("from bar; from base", base_symbol.base_example());
143        assert_eq!(0.0, base_symbol.x());
144
145        let symbol = FooBarBar::new(&arena, 10.0, "bar bar");
146        let base_symbol: Thingy = symbol.into();
147        assert_eq!("FooBarBar", base_symbol.name());
148        assert_eq!(true, base_symbol.is::<Foo>());
149        assert_eq!(true, base_symbol.is::<FooBar>());
150        assert_eq!(true, base_symbol.is::<FooBarBar>());
151        assert_eq!(false, base_symbol.is::<FooQux>());
152        assert_eq!("from bar bar; from bar; from base", base_symbol.base_example());
153        assert_eq!(10.0, base_symbol.x());
154
155        let symbol = FooQux::new(&arena);
156        let base_symbol: Thingy = symbol.into();
157        assert_eq!("FooQux", base_symbol.name());
158        assert_eq!(true, base_symbol.is::<Foo>());
159        assert_eq!(false, base_symbol.is::<FooBar>());
160        assert_eq!(true, base_symbol.is::<FooQux>());
161        assert_eq!(0.0, base_symbol.x());
162    }
163}