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 struct Thingy {
44 pub fn Thingy() {
45 super();
46 }
47
48 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}