hydroperfox_smodel/
lib.rs1use std::{cell::RefCell, rc::{Rc, Weak}};
2use std::fmt::Debug;
3
4pub mod util;
5
6pub use hydroperfox_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 pub fn clean(&self) {
29 let mut data = self.data.borrow_mut();
30 let mut i = data.len();
31 while i != 0 {
32 i -= 1;
33 let obj = data.get(i).unwrap();
34 if Rc::weak_count(obj) == 0 && Rc::strong_count(obj) == 1 {
35 data.remove(i);
36 }
37 }
38 }
39}
40
41#[derive(Debug)]
42pub enum SModelError {
43 Contravariant,
44}
45
46#[cfg(test)]
47mod test {
48 #[test]
49 fn test() {
50 use crate::smodel;
51
52 smodel! {
53 mod smodel = crate;
54
55 type Arena = Arena;
56
57 struct Thingy {
59 pub fn Thingy() {
60 super();
61 }
62
63 pub fn name(&self) -> String {
65 "".into()
66 }
67
68 pub fn base_example(&self) -> String {
69 "from base".into()
70 }
71
72 pub fn x(&self) -> f64 {
73 0.0
74 }
75 }
76
77 struct Foo: Thingy {
78 pub fn Foo() {
79 super();
80 }
81
82 #[inheritdoc]
83 pub override fn name(&self) -> String {
84 "Foo".into()
85 }
86 }
87
88 struct FooBar: Foo {
89 pub fn FooBar() {
90 super();
91 }
92
93 #[inheritdoc]
94 pub override fn name(&self) -> String {
95 "FooBar".into()
96 }
97
98 pub override fn base_example(&self) -> String {
99 format!("from bar; {}", super.base_example())
100 }
101 }
102
103 struct FooBarBar: FooBar {
104 let m_x: f64 = 0.0;
105 let ref m_y: String = "".into();
106
107 pub fn FooBarBar(x: f64, y: &str) {
108 super();
109 self.set_m_x(x);
110 self.set_m_y(y.into());
111 }
112
113 #[inheritdoc]
114 pub override fn name(&self) -> String {
115 "FooBarBar".into()
116 }
117
118 pub override fn x(&self) -> f64 {
119 self.m_x()
120 }
121
122 pub override fn base_example(&self) -> String {
123 format!("from {}; {}", self.m_y(), super.base_example())
124 }
125 }
126
127 struct FooQux: Foo {
128 pub fn FooQux() {
129 super();
130 }
131
132 #[inheritdoc]
133 pub override fn name(&self) -> String {
134 "FooQux".into()
135 }
136 }
137 }
138
139 let arena = Arena::new();
140
141 let symbol = Foo::new(&arena);
142 let base_symbol: Thingy = symbol.into();
143 assert_eq!("Foo", base_symbol.name());
144 assert_eq!(true, base_symbol.is::<Foo>());
145 assert_eq!(false, base_symbol.is::<FooBar>());
146 assert_eq!(false, base_symbol.is::<FooQux>());
147 assert_eq!("from base", base_symbol.base_example());
148 assert_eq!(0.0, base_symbol.x());
149
150 let symbol = FooBar::new(&arena);
151 let base_symbol: Thingy = symbol.into();
152 assert_eq!("FooBar", base_symbol.name());
153 assert_eq!(true, base_symbol.is::<Foo>());
154 assert_eq!(true, base_symbol.is::<FooBar>());
155 assert_eq!(false, base_symbol.is::<FooBarBar>());
156 assert_eq!(false, base_symbol.is::<FooQux>());
157 assert_eq!("from bar; from base", base_symbol.base_example());
158 assert_eq!(0.0, base_symbol.x());
159
160 let symbol = FooBarBar::new(&arena, 10.0, "bar bar");
161 let base_symbol: Thingy = symbol.into();
162 assert_eq!("FooBarBar", base_symbol.name());
163 assert_eq!(true, base_symbol.is::<Foo>());
164 assert_eq!(true, base_symbol.is::<FooBar>());
165 assert_eq!(true, base_symbol.is::<FooBarBar>());
166 assert_eq!(false, base_symbol.is::<FooQux>());
167 assert_eq!("from bar bar; from bar; from base", base_symbol.base_example());
168 assert_eq!(10.0, base_symbol.x());
169
170 let symbol = FooQux::new(&arena);
171 let base_symbol: Thingy = symbol.into();
172 assert_eq!("FooQux", base_symbol.name());
173 assert_eq!(true, base_symbol.is::<Foo>());
174 assert_eq!(false, base_symbol.is::<FooBar>());
175 assert_eq!(true, base_symbol.is::<FooQux>());
176 assert_eq!(0.0, base_symbol.x());
177 }
178}