Skip to main content

riddle/
core.rs

1use crate::{
2    RiddleError,
3    env::{Atom, AtomId, BoolExpr, CommonEnv, Env, Object, ObjectId, Slot},
4    language::{Disjunction, execute},
5    parse_problem,
6    scope::{BoolType, Class, CommonScope, Field, Function, IntType, Predicate, RealType, Scope, StringType, Type},
7};
8use std::{
9    cell::RefCell,
10    collections::HashMap,
11    rc::{Rc, Weak},
12};
13
14pub trait Core: Scope + Env {
15    fn new_bool(&self, value: bool) -> Slot;
16    fn new_bool_var(&self) -> Slot;
17    fn new_int(&self, value: i64) -> Slot;
18    fn new_int_var(&self) -> Slot;
19    fn new_real(&self, num: i64, den: i64) -> Slot;
20    fn new_real_var(&self) -> Slot;
21    fn new_string(&self, value: &str) -> Slot;
22    fn new_string_var(&self) -> Slot;
23
24    fn sum(&self, sum: &[Slot]) -> Result<Slot, RiddleError>;
25    fn opposite(&self, term: Slot) -> Result<Slot, RiddleError>;
26    fn mul(&self, mul: &[Slot]) -> Result<Slot, RiddleError>;
27    fn div(&self, left: Slot, right: Slot) -> Result<Slot, RiddleError>;
28
29    fn assert(&self, term: Rc<BoolExpr>) -> bool;
30    fn new_var(&self, tp: Rc<dyn Class>, instances: &[ObjectId]) -> Result<Slot, RiddleError>;
31    fn new_disjunction(&self, disjunction: Disjunction);
32
33    fn new_object(&self, class: Rc<dyn Class>) -> ObjectId;
34    fn get_object(&self, id: ObjectId) -> Option<Rc<Object>>;
35    fn new_atom(&self, predicate: Rc<Predicate>, fact: bool, args: HashMap<String, Slot>) -> AtomId;
36    fn get_atom(&self, id: AtomId) -> Option<Rc<Atom>>;
37
38    fn bool_type(&self) -> Rc<BoolType> {
39        self.get_type("bool").expect("Core should have bool type").as_any().downcast::<BoolType>().expect("Core bool type should be BoolType")
40    }
41
42    fn int_type(&self) -> Rc<IntType> {
43        self.get_type("int").expect("Core should have int type").as_any().downcast::<IntType>().expect("Core int type should be IntType")
44    }
45
46    fn real_type(&self) -> Rc<RealType> {
47        self.get_type("real").expect("Core should have real type").as_any().downcast::<RealType>().expect("Core real type should be RealType")
48    }
49
50    fn string_type(&self) -> Rc<StringType> {
51        self.get_type("string").expect("Core should have string type").as_any().downcast::<StringType>().expect("Core string type should be StringType")
52    }
53}
54
55pub struct CommonCore {
56    scope: Rc<CommonScope>,
57    env: Rc<CommonEnv>,
58    objects: RefCell<Vec<Rc<Object>>>,
59    atoms: RefCell<Vec<Rc<Atom>>>,
60}
61
62impl CommonCore {
63    pub fn new(core: Weak<dyn Core>) -> Rc<Self> {
64        let c_core = Rc::new(CommonCore {
65            scope: Rc::new(CommonScope::new(core.clone(), None)),
66            env: Rc::new(CommonEnv::new(None)),
67            objects: RefCell::new(Vec::new()),
68            atoms: RefCell::new(Vec::new()),
69        });
70        c_core.add_type(Rc::new(BoolType::new(core.clone())));
71        c_core.add_type(Rc::new(IntType::new(core.clone())));
72        c_core.add_type(Rc::new(RealType::new(core.clone())));
73        c_core.add_type(Rc::new(StringType::new(core.clone())));
74        c_core
75    }
76
77    /// Parses and executes a RiDDLe problem in this core context.
78    ///
79    /// The parsed problem metadata is registered in the current scope,
80    /// then each statement is executed in order using this core scope
81    /// and environment.
82    ///
83    /// Returns an error if parsing or execution fails.
84    pub fn read(&self, riddle: &str) -> Result<(), RiddleError> {
85        let mut problem = parse_problem(riddle)?;
86        let statments = std::mem::take(&mut problem.statements);
87        self.scope.clone().add_problem(problem);
88        let scope: Rc<dyn Scope> = self.scope.clone();
89        for stmt in statments {
90            execute(&scope, self.env.clone(), &stmt)?;
91        }
92        Ok(())
93    }
94
95    /// Registers a type in the core type table under its declared name.
96    pub fn add_type(&self, tp: Rc<dyn Type>) {
97        self.scope.types.borrow_mut().insert(tp.name().to_string(), tp);
98    }
99
100    pub fn get_objects(&self) -> Vec<Rc<Object>> {
101        self.objects.borrow().clone()
102    }
103
104    pub fn get_object(&self, id: ObjectId) -> Option<Rc<Object>> {
105        self.objects.borrow().get(*id).cloned()
106    }
107
108    pub fn new_object(&self, class: Rc<dyn Class>) -> ObjectId {
109        let id = ObjectId(self.objects.borrow().len());
110        self.objects.borrow_mut().push(Rc::new(Object::new(id, class)));
111        id
112    }
113
114    pub fn get_atoms(&self) -> Vec<Rc<Atom>> {
115        self.atoms.borrow().clone()
116    }
117
118    pub fn get_atom(&self, id: AtomId) -> Option<Rc<Atom>> {
119        self.atoms.borrow().get(*id).cloned()
120    }
121
122    pub fn new_atom(&self, predicate: Rc<Predicate>, fact: bool, args: HashMap<String, Slot>) -> AtomId {
123        let id = AtomId(self.atoms.borrow().len());
124        predicate.atoms.borrow_mut().push(id);
125        self.atoms.borrow_mut().push(Rc::new(Atom::new(id, predicate, fact, args)));
126        id
127    }
128}
129
130impl Scope for CommonCore {
131    fn core(&self) -> Rc<dyn Core> {
132        self.scope.clone().core()
133    }
134
135    fn scope(&self) -> Option<Rc<dyn Scope>> {
136        None
137    }
138
139    fn get_fields(&self) -> Vec<Rc<Field>> {
140        self.scope.get_fields()
141    }
142
143    fn get_field(&self, name: &str) -> Option<Rc<Field>> {
144        self.scope.get_field(name)
145    }
146
147    fn get_function(&self, name: &str, types: &[Rc<dyn Type>]) -> Option<Rc<Function>> {
148        self.scope.get_function(name, types)
149    }
150
151    fn get_type(&self, name: &str) -> Option<Rc<dyn Type>> {
152        self.scope.get_type(name)
153    }
154
155    fn get_predicate(&self, name: &str) -> Option<Rc<Predicate>> {
156        self.scope.get_predicate(name)
157    }
158}
159
160impl Env for CommonCore {
161    fn parent(&self) -> Option<Rc<dyn Env>> {
162        None
163    }
164
165    fn get(&self, name: &str) -> Option<Slot> {
166        self.env.get(name)
167    }
168
169    fn set(&self, name: String, value: Slot) {
170        self.env.set(name, value);
171    }
172}
173
174#[cfg(test)]
175mod tests {
176    use super::*;
177    use crate::{env::Var, scope::arith_type};
178    use std::any::Any;
179
180    struct TestObject {
181        tp: Weak<dyn Type>,
182    }
183
184    impl TestObject {
185        fn new(var_type: Rc<dyn Type>) -> Self {
186            Self { tp: Rc::downgrade(&var_type) }
187        }
188    }
189
190    impl Var for TestObject {
191        fn var_type(&self) -> Rc<dyn Type> {
192            self.tp.upgrade().expect("Type should still exist")
193        }
194
195        fn as_any(self: Rc<Self>) -> Rc<dyn Any> {
196            self
197        }
198    }
199
200    struct TestCore {
201        core: Rc<CommonCore>,
202    }
203
204    impl TestCore {
205        fn new() -> Rc<Self> {
206            Rc::new_cyclic(|core| Self {
207                core: {
208                    let core: Weak<TestCore> = core.clone();
209                    CommonCore::new(core)
210                },
211            })
212        }
213
214        fn read(&self, riddle: &str) -> Result<(), RiddleError> {
215            self.core.read(riddle)
216        }
217    }
218
219    impl Core for TestCore {
220        fn new_bool(&self, _value: bool) -> Slot {
221            Slot::Primitive(Rc::new(TestObject::new(self.bool_type())))
222        }
223        fn new_bool_var(&self) -> Slot {
224            Slot::Primitive(Rc::new(TestObject::new(self.bool_type())))
225        }
226        fn new_int(&self, _value: i64) -> Slot {
227            Slot::Primitive(Rc::new(TestObject::new(self.int_type())))
228        }
229        fn new_int_var(&self) -> Slot {
230            Slot::Primitive(Rc::new(TestObject::new(self.int_type())))
231        }
232        fn new_real(&self, _num: i64, _den: i64) -> Slot {
233            Slot::Primitive(Rc::new(TestObject::new(self.real_type())))
234        }
235        fn new_real_var(&self) -> Slot {
236            Slot::Primitive(Rc::new(TestObject::new(self.real_type())))
237        }
238        fn new_string(&self, _value: &str) -> Slot {
239            Slot::Primitive(Rc::new(TestObject::new(self.string_type())))
240        }
241        fn new_string_var(&self) -> Slot {
242            Slot::Primitive(Rc::new(TestObject::new(self.string_type())))
243        }
244
245        fn sum(&self, sum: &[Slot]) -> Result<Slot, RiddleError> {
246            let tp = arith_type(self, sum)?;
247            Ok(Slot::Primitive(Rc::new(TestObject::new(tp))))
248        }
249        fn opposite(&self, term: Slot) -> Result<Slot, RiddleError> {
250            let tp = match term {
251                Slot::Primitive(var) => var.var_type(),
252                Slot::ObjectRef(id) => self.get_object(id).expect("Object should exist").class(),
253                Slot::AtomRef(id) => self.get_atom(id).expect("Atom should exist").predicate(),
254            };
255            Ok(Slot::Primitive(Rc::new(TestObject::new(tp))))
256        }
257        fn mul(&self, mul: &[Slot]) -> Result<Slot, RiddleError> {
258            let tp = arith_type(self, mul)?;
259            Ok(Slot::Primitive(Rc::new(TestObject::new(tp))))
260        }
261        fn div(&self, left: Slot, right: Slot) -> Result<Slot, RiddleError> {
262            let tp = arith_type(self, &[left, right])?;
263            Ok(Slot::Primitive(Rc::new(TestObject::new(tp))))
264        }
265
266        fn assert(&self, _term: Rc<BoolExpr>) -> bool {
267            true
268        }
269
270        fn new_var(&self, class: Rc<dyn Class>, instances: &[ObjectId]) -> Result<Slot, RiddleError> {
271            if instances.is_empty() {
272                return Err(RiddleError::InconsistencyError("Cannot create variable with no instances".into()));
273            }
274            Ok(Slot::Primitive(Rc::new(TestObject::new(class))))
275        }
276        fn new_disjunction(&self, _disjunction: Disjunction) {}
277
278        fn new_object(&self, class: Rc<dyn Class>) -> ObjectId {
279            self.core.new_object(class)
280        }
281        fn get_object(&self, id: ObjectId) -> Option<Rc<Object>> {
282            self.core.get_object(id)
283        }
284        fn new_atom(&self, predicate: Rc<Predicate>, fact: bool, args: HashMap<String, Slot>) -> AtomId {
285            self.core.new_atom(predicate, fact, args)
286        }
287        fn get_atom(&self, id: AtomId) -> Option<Rc<Atom>> {
288            self.core.get_atom(id)
289        }
290    }
291
292    impl Scope for TestCore {
293        fn core(&self) -> Rc<dyn Core> {
294            panic!("Core should not call scope core function")
295        }
296
297        fn scope(&self) -> Option<Rc<dyn Scope>> {
298            None
299        }
300
301        fn get_fields(&self) -> Vec<Rc<Field>> {
302            self.core.get_fields()
303        }
304
305        fn get_field(&self, _name: &str) -> Option<Rc<Field>> {
306            self.core.get_field(_name)
307        }
308
309        fn get_function(&self, name: &str, types: &[Rc<dyn Type>]) -> Option<Rc<Function>> {
310            self.core.get_function(name, types)
311        }
312
313        fn get_type(&self, name: &str) -> Option<Rc<dyn Type>> {
314            self.core.get_type(name)
315        }
316
317        fn get_predicate(&self, name: &str) -> Option<Rc<Predicate>> {
318            self.core.get_predicate(name)
319        }
320    }
321
322    impl Env for TestCore {
323        fn parent(&self) -> Option<Rc<dyn Env>> {
324            None
325        }
326
327        fn get(&self, name: &str) -> Option<Slot> {
328            self.core.get(name)
329        }
330
331        fn set(&self, name: String, value: Slot) {
332            self.core.set(name, value);
333        }
334    }
335
336    #[test]
337    fn create_core() {
338        let core = TestCore::new();
339        assert!(core.get_type("bool").is_some());
340        assert!(core.get_type("int").is_some());
341        assert!(core.get_type("real").is_some());
342        assert!(core.get_type("string").is_some());
343    }
344
345    #[test]
346    fn read_problem() {
347        let core = TestCore::new();
348        core.read("bool a, b, c; (a & b) | c;").expect("Failed to read problem with boolean variables and expression");
349    }
350}