Skip to main content

riddle/
scope.rs

1use crate::{
2    RiddleError,
3    core::Core,
4    env::{Atom, AtomId, BoolExpr, CommonEnv, Env, ObjectId, Slot, Var},
5    language::{ClassDef, ConstructorDef, Expr, FunctionDef, PredicateDef, ProblemDef, Statement, evaluate, execute},
6};
7use std::{
8    cell::RefCell,
9    collections::HashMap,
10    fmt,
11    rc::{Rc, Weak},
12};
13
14pub trait Type {
15    /// Returns the simple name of the type.
16    fn name(&self) -> &str;
17    /// Returns the fully qualified name of the type, including any parent class names.
18    fn full_name(&self) -> String {
19        self.name().to_string()
20    }
21    fn as_class(self: Rc<Self>) -> Option<Rc<dyn Class>> {
22        None
23    }
24
25    /// Creates a new instance of the type, returning a [`Slot`] that can be used
26    fn new_instance(self: Rc<Self>) -> Slot;
27}
28
29pub struct BoolType {
30    core: Weak<dyn Core>,
31}
32
33impl BoolType {
34    /// Creates the built-in boolean type.
35    pub fn new(core: Weak<dyn Core>) -> Self {
36        Self { core }
37    }
38}
39
40impl Type for BoolType {
41    fn name(&self) -> &str {
42        "bool"
43    }
44
45    fn new_instance(self: Rc<Self>) -> Slot {
46        let var_type = Rc::downgrade(&self);
47        Slot::Primitive(Rc::new(BoolExpr::Term { var_type, term: self.core.upgrade().unwrap().new_bool_var() }))
48    }
49}
50
51pub struct IntType {
52    core: Weak<dyn Core>,
53}
54
55impl IntType {
56    /// Creates the built-in integer type.
57    pub fn new(core: Weak<dyn Core>) -> Self {
58        Self { core }
59    }
60}
61
62impl Type for IntType {
63    fn name(&self) -> &str {
64        "int"
65    }
66
67    fn new_instance(self: Rc<Self>) -> Slot {
68        self.core.upgrade().unwrap().new_int_var()
69    }
70}
71
72pub struct RealType {
73    core: Weak<dyn Core>,
74}
75
76impl RealType {
77    /// Creates the built-in real (floating-point) type.
78    pub fn new(core: Weak<dyn Core>) -> Self {
79        Self { core }
80    }
81}
82
83impl Type for RealType {
84    fn name(&self) -> &str {
85        "real"
86    }
87
88    fn new_instance(self: Rc<Self>) -> Slot {
89        self.core.upgrade().unwrap().new_real_var()
90    }
91}
92
93pub struct StringType {
94    core: Weak<dyn Core>,
95}
96
97impl StringType {
98    /// Creates the built-in string type.
99    pub fn new(core: Weak<dyn Core>) -> Self {
100        Self { core }
101    }
102}
103
104impl Type for StringType {
105    fn name(&self) -> &str {
106        "string"
107    }
108
109    fn new_instance(self: Rc<Self>) -> Slot {
110        self.core.upgrade().unwrap().new_string_var()
111    }
112}
113
114pub struct Field {
115    name: String,
116    field_type: Vec<String>,
117    default: Option<Expr>,
118}
119
120impl Field {
121    /// Creates a new field descriptor.
122    pub fn new(name: String, field_type: Vec<String>, default: Option<Expr>) -> Self {
123        Self { name, field_type, default }
124    }
125
126    pub fn name(&self) -> &str {
127        &self.name
128    }
129
130    pub fn field_type(&self) -> &[String] {
131        &self.field_type
132    }
133
134    pub fn default(&self) -> Option<&Expr> {
135        self.default.as_ref()
136    }
137}
138
139pub trait Scope {
140    fn core(&self) -> Rc<dyn Core>;
141    fn scope(&self) -> Option<Rc<dyn Scope>>;
142    fn as_class(self: Rc<Self>) -> Option<Rc<dyn Class>> {
143        None
144    }
145
146    fn get_fields(&self) -> Vec<Rc<Field>>;
147    fn get_field(&self, name: &str) -> Option<Rc<Field>>;
148    fn get_function(&self, name: &str, types: &[Rc<dyn Type>]) -> Option<Rc<Function>>;
149    fn get_type(&self, name: &str) -> Option<Rc<dyn Type>>;
150    fn get_predicate(&self, name: &str) -> Option<Rc<Predicate>>;
151}
152
153pub struct CommonScope {
154    core: Weak<dyn Core>,
155    scope: Option<Weak<dyn Scope>>,
156    fields: RefCell<HashMap<String, Rc<Field>>>,
157    functions: RefCell<HashMap<String, Vec<Rc<Function>>>>,
158    pub(crate) types: RefCell<HashMap<String, Rc<dyn Type>>>,
159    predicates: RefCell<HashMap<String, Rc<Predicate>>>,
160}
161
162impl CommonScope {
163    /// Creates an empty scope with an optional parent scope.
164    pub fn new(core: Weak<dyn Core>, scope: Option<Weak<dyn Scope>>) -> Self {
165        Self {
166            core,
167            scope,
168            fields: RefCell::new(HashMap::new()),
169            functions: RefCell::new(HashMap::new()),
170            types: RefCell::new(HashMap::new()),
171            predicates: RefCell::new(HashMap::new()),
172        }
173    }
174
175    /// Builds a scope populated from a class definition.
176    pub fn from_class(parent_scope: Weak<dyn Scope>, class: ClassDef) -> Rc<Self> {
177        let scope = Rc::new(Self::new(Rc::downgrade(&parent_scope.upgrade().expect("Scope should be valid when building class scope").core()), Some(parent_scope)));
178        let weak_scope = Rc::downgrade(&scope);
179        for (field_type, fields) in class.fields {
180            for (name, default) in fields {
181                scope.fields.borrow_mut().insert(name.clone(), Rc::new(Field { name, field_type: field_type.clone(), default }));
182            }
183        }
184        for function_def in class.functions {
185            scope.functions.borrow_mut().entry(function_def.name.clone()).or_default().push(Function::new(weak_scope.clone(), function_def));
186        }
187        for class_def in class.classes {
188            let class_name = class_def.name.clone();
189            scope.types.borrow_mut().insert(class_name, CommonClass::new(weak_scope.clone(), class_def));
190        }
191        for predicate_def in class.predicates {
192            scope.predicates.borrow_mut().insert(predicate_def.name.clone(), Predicate::new(weak_scope.clone(), predicate_def));
193        }
194        scope
195    }
196
197    /// Builds a local scope for constructor arguments.
198    pub fn from_constructor(parent_scope: Weak<dyn Class>, constructor: ConstructorDef) -> Self {
199        let scope = Self::new(Rc::downgrade(&parent_scope.upgrade().expect("Class should be valid when building constructor scope").core()), Some(parent_scope));
200        for (arg_type, arg_name) in constructor.args {
201            scope.fields.borrow_mut().insert(arg_name.clone(), Rc::new(Field { name: arg_name, field_type: arg_type, default: None }));
202        }
203        scope
204    }
205
206    /// Builds a local scope for function arguments.
207    pub fn from_function(parent_scope: Weak<dyn Scope>, function: FunctionDef) -> Self {
208        let scope = Self::new(Rc::downgrade(&parent_scope.upgrade().expect("Scope should be valid when building function scope").core()), Some(parent_scope));
209        for (arg_type, arg_name) in function.args {
210            scope.fields.borrow_mut().insert(arg_name.clone(), Rc::new(Field { name: arg_name, field_type: arg_type, default: None }));
211        }
212        scope
213    }
214
215    /// Builds a local scope for predicate arguments.
216    pub fn from_predicate(parent_scope: Weak<dyn Scope>, predicate: PredicateDef) -> Self {
217        let scope = Self::new(Rc::downgrade(&parent_scope.upgrade().expect("Scope should be valid when building predicate scope").core()), Some(parent_scope));
218        for (arg_type, arg_name) in predicate.args {
219            scope.fields.borrow_mut().insert(arg_name.clone(), Rc::new(Field { name: arg_name, field_type: arg_type, default: None }));
220        }
221        scope
222    }
223
224    /// Merges problem-level declarations into this scope.
225    pub fn add_problem(self: Rc<Self>, problem: ProblemDef) {
226        let scope = Rc::downgrade(&self);
227        for function_def in problem.functions {
228            self.functions.borrow_mut().entry(function_def.name.clone()).or_default().push(Function::new(scope.clone(), function_def));
229        }
230        for class_def in problem.classes {
231            self.types.borrow_mut().insert(class_def.name.clone(), CommonClass::new(scope.clone(), class_def));
232        }
233        for predicate_def in problem.predicates {
234            self.predicates.borrow_mut().insert(predicate_def.name.clone(), Predicate::new(scope.clone(), predicate_def));
235        }
236    }
237}
238
239impl Scope for CommonScope {
240    fn core(&self) -> Rc<dyn Core> {
241        self.core.upgrade().expect("Core should never be dropped while scopes exist")
242    }
243
244    fn scope(&self) -> Option<Rc<dyn Scope>> {
245        self.scope.as_ref()?.upgrade()
246    }
247
248    fn get_type(&self, name: &str) -> Option<Rc<dyn Type>> {
249        self.types.borrow().get(name).cloned().or_else(|| self.scope()?.get_type(name))
250    }
251
252    fn get_predicate(&self, name: &str) -> Option<Rc<Predicate>> {
253        self.predicates.borrow().get(name).cloned().or_else(|| self.scope()?.get_predicate(name))
254    }
255
256    fn get_fields(&self) -> Vec<Rc<Field>> {
257        self.fields.borrow().values().cloned().collect()
258    }
259
260    fn get_field(&self, name: &str) -> Option<Rc<Field>> {
261        self.fields.borrow().get(name).cloned().or_else(|| self.scope()?.get_field(name))
262    }
263
264    fn get_function(&self, name: &str, types: &[Rc<dyn Type>]) -> Option<Rc<Function>> {
265        self.functions
266            .borrow()
267            .get(name)
268            .and_then(|functions| {
269                functions
270                    .iter()
271                    .find(|function| {
272                        if function.args().len() != types.len() {
273                            return false;
274                        }
275                        for (class, arg_type) in types.iter().zip(function.args().iter().map(|(t, _)| t)) {
276                            if !get_type_by_path(self, arg_type).ok().is_some_and(|t| is_assignable_from(&t, class)) {
277                                return false;
278                            }
279                        }
280                        true
281                    })
282                    .cloned()
283            })
284            .or_else(|| self.scope.as_ref()?.upgrade()?.get_function(name, types))
285    }
286}
287
288/// Executable constructor declaration.
289pub struct Constructor {
290    scope: Rc<CommonScope>,
291    args: Vec<(Vec<String>, String)>,
292    init: Vec<(Vec<String>, Vec<Expr>)>,
293    statements: Vec<Statement>,
294}
295
296impl Constructor {
297    /// Creates a constructor from its parsed definition.
298    pub fn new(parent_scope: Weak<dyn Class>, mut constructor: ConstructorDef) -> Self {
299        Self {
300            args: std::mem::take(&mut constructor.args),
301            statements: std::mem::take(&mut constructor.statements),
302            init: std::mem::take(&mut constructor.init),
303            scope: Rc::new(CommonScope::from_constructor(parent_scope, constructor)),
304        }
305    }
306
307    pub fn args(&self) -> &[(Vec<String>, String)] {
308        &self.args
309    }
310
311    pub fn statements(&self) -> &[Statement] {
312        &self.statements
313    }
314
315    /// Creates a new object instance and runs constructor statements.
316    pub fn call(&self, object: ObjectId, args: Vec<Slot>) -> Result<(), RiddleError> {
317        if args.len() != self.args.len() {
318            return Err(RiddleError::RuntimeError(format!("Expected {} arguments, got {}", self.args.len(), args.len())));
319        }
320        let obj_env = self.core().get_object(object).ok_or_else(|| RiddleError::NotFound(format!("Object {} not found", *object)))?.as_env().ok_or_else(|| RiddleError::RuntimeError("Object environment not found".into()))?;
321        // the context in which the constructor is invoked..
322        let constructor_env = Rc::new(CommonEnv::new(Some(obj_env.clone())));
323        constructor_env.set("this".to_string(), Slot::ObjectRef(object));
324        for ((arg_type, arg_name), arg_value) in self.args.iter().zip(args) {
325            let expected_type = get_type_by_path(self.scope.as_ref(), arg_type)?;
326            let arg_value_type = match &arg_value {
327                Slot::Primitive(p) => p.var_type(),
328                Slot::ObjectRef(obj_id) => self.scope.core().get_object(*obj_id).ok_or_else(|| RiddleError::NotFound(format!("Object {}", *obj_id)))?.var_type(),
329                Slot::AtomRef(atom_id) => self.scope.core().get_atom(*atom_id).ok_or_else(|| RiddleError::NotFound(format!("Atom {}", *atom_id)))?.var_type(),
330            };
331            if !is_assignable_from(&expected_type, &arg_value_type) {
332                return Err(RiddleError::TypeError(format!("Argument '{}' expected to be of type '{}', got '{}'", arg_name, expected_type.full_name(), arg_value_type.full_name())));
333            }
334            constructor_env.set(arg_name.clone(), arg_value);
335        }
336
337        let class = self.scope.scope.as_ref().and_then(|s| s.upgrade()).and_then(|s| s.as_class()).ok_or_else(|| RiddleError::RuntimeError("Constructor is not defined within a class".into()))?;
338        // we first execute parent constructors in declaration order, passing specified arguments or defaults if provided..
339        for parent in class.parents() {
340            let parent_class = get_type_by_path(self.scope.as_ref(), parent)?.as_class().ok_or_else(|| RiddleError::NotAClass(parent.join(".")))?;
341            if let Some((_, init_exprs)) = self.init.iter().find(|(init_field, _)| init_field.iter().map(|s| s.as_str()).eq(parent.iter().map(|s| s.as_str()))) {
342                let exprs = init_exprs.iter().map(|e| evaluate(self.scope.as_ref(), constructor_env.clone(), e)).collect::<Result<Vec<_>, _>>()?;
343                let types = exprs
344                    .iter()
345                    .map(|e| match e {
346                        Slot::Primitive(p) => Ok(p.var_type()),
347                        Slot::ObjectRef(obj_id) => Ok(self.scope.core().get_object(*obj_id).ok_or_else(|| RiddleError::NotFound(format!("Object {}", *obj_id)))?.var_type()),
348                        Slot::AtomRef(atom_id) => Ok(self.scope.core().get_atom(*atom_id).ok_or_else(|| RiddleError::NotFound(format!("Atom {}", *atom_id)))?.var_type()),
349                    })
350                    .collect::<Result<Vec<_>, _>>()?;
351                let constructor = parent_class.constructor(&types).ok_or_else(|| RiddleError::NotFound(format!("Constructor for parent class '{}' with specified argument types", parent_class.full_name())))?;
352                constructor.call(object, exprs)?;
353            } else {
354                let constructor = parent_class.constructor(&[]).ok_or_else(|| RiddleError::NotFound(format!("No-arg constructor for parent class '{}'", parent_class.full_name())))?;
355                constructor.call(object, vec![])?;
356            }
357        }
358
359        // we then populate fields declared in this class..
360        for field in class.get_fields() {
361            let fld_tp = get_type_by_path(self.scope.as_ref(), field.field_type())?;
362            if obj_env.get(field.name()).is_none() {
363                if let Some(default_expr) = field.default() {
364                    let value = evaluate(self.scope.as_ref(), constructor_env.clone(), default_expr)?;
365                    let value_type = match &value {
366                        Slot::Primitive(p) => p.var_type(),
367                        Slot::ObjectRef(obj_id) => self.scope.core().get_object(*obj_id).ok_or_else(|| RiddleError::NotFound(format!("Object {}", *obj_id)))?.var_type(),
368                        Slot::AtomRef(atom_id) => self.scope.core().get_atom(*atom_id).ok_or_else(|| RiddleError::NotFound(format!("Atom {}", *atom_id)))?.var_type(),
369                    };
370                    if !is_assignable_from(&fld_tp, &value_type) {
371                        return Err(RiddleError::TypeError(format!("Field '{}' expected to be of type '{}', got '{}'", field.name(), fld_tp.full_name(), value_type.full_name())));
372                    }
373                    obj_env.set(field.name().to_string(), value);
374                } else if let Some(class) = fld_tp.clone().as_class() {
375                    let instances = class.instances();
376                    if instances.is_empty() {
377                        return Err(RiddleError::RuntimeError(format!("No instances found for field '{}' of type '{}'", field.name(), class.full_name())));
378                    } else if instances.len() == 1 {
379                        obj_env.set(field.name().to_string(), Slot::ObjectRef(instances[0]));
380                    } else {
381                        obj_env.set(field.name().to_string(), self.scope.clone().core().new_var(class, &instances)?);
382                    }
383                } else {
384                    obj_env.set(field.name().to_string(), fld_tp.clone().new_instance());
385                }
386            }
387        }
388
389        // finally, we execute constructor statements in the context of the new object..
390        let scope: Rc<dyn Scope> = self.scope.clone();
391        for stmt in &self.statements {
392            execute(&scope, constructor_env.clone(), stmt)?;
393        }
394        Ok(())
395    }
396}
397
398impl Scope for Constructor {
399    fn core(&self) -> Rc<dyn Core> {
400        self.scope.core()
401    }
402
403    fn scope(&self) -> Option<Rc<dyn Scope>> {
404        self.scope.scope()
405    }
406
407    fn get_fields(&self) -> Vec<Rc<Field>> {
408        self.scope.get_fields()
409    }
410
411    fn get_field(&self, name: &str) -> Option<Rc<Field>> {
412        self.scope.get_field(name)
413    }
414
415    fn get_function(&self, name: &str, types: &[Rc<dyn Type>]) -> Option<Rc<Function>> {
416        self.scope.get_function(name, types)
417    }
418
419    fn get_type(&self, name: &str) -> Option<Rc<dyn Type>> {
420        self.scope.get_type(name)
421    }
422
423    fn get_predicate(&self, name: &str) -> Option<Rc<Predicate>> {
424        self.scope.get_predicate(name)
425    }
426}
427
428impl fmt::Display for Constructor {
429    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
430        let class_name = self.scope.scope.as_ref().and_then(|s| s.upgrade()).and_then(|s| s.as_class()).map(|c| c.full_name()).unwrap_or_else(|| "<unknown class>".to_string());
431        let args = self.args.iter().map(|(t, n)| format!("{} {}", t.join("."), n)).collect::<Vec<_>>().join(", ");
432        write!(f, "{}({})", class_name, args)
433    }
434}
435
436pub struct Function {
437    scope: Rc<CommonScope>,
438    name: String,
439    return_type: Option<Vec<String>>,
440    args: Vec<(Vec<String>, String)>,
441    statements: Vec<Statement>,
442}
443
444impl Function {
445    /// Creates a function from its parsed definition.
446    pub fn new(parent_scope: Weak<dyn Scope>, mut function: FunctionDef) -> Rc<Self> {
447        Rc::new(Self {
448            name: std::mem::take(&mut function.name),
449            return_type: std::mem::take(&mut function.return_type),
450            args: std::mem::take(&mut function.args),
451            statements: std::mem::take(&mut function.statements),
452            scope: Rc::new(CommonScope::from_function(parent_scope, function)),
453        })
454    }
455
456    pub fn name(&self) -> &str {
457        &self.name
458    }
459
460    pub fn return_type(&self) -> Option<&[String]> {
461        self.return_type.as_deref()
462    }
463
464    pub fn args(&self) -> &[(Vec<String>, String)] {
465        &self.args
466    }
467
468    pub fn statements(&self) -> &[Statement] {
469        &self.statements
470    }
471
472    /// Invokes the function in a fresh local environment.
473    ///
474    /// The call validates argument count and type compatibility, executes all
475    /// function statements, and checks the declared return type (if any).
476    pub fn call(&self, env: Rc<dyn Env>, args: Vec<Slot>) -> Result<Option<Slot>, RiddleError> {
477        if args.len() != self.args.len() {
478            return Err(RiddleError::RuntimeError(format!("Expected {} arguments, got {}", self.args.len(), args.len())));
479        }
480        let function_env = Rc::new(CommonEnv::new(Some(env)));
481        for ((arg_type, arg_name), arg_value) in self.args.iter().zip(args) {
482            let expected_type = get_type_by_path(self.scope.as_ref(), arg_type)?;
483            let arg_value_type = match &arg_value {
484                Slot::Primitive(p) => p.var_type(),
485                Slot::ObjectRef(obj_id) => self.scope.core().get_object(*obj_id).ok_or_else(|| RiddleError::NotFound(format!("Object {}", *obj_id)))?.var_type(),
486                Slot::AtomRef(atom_id) => self.scope.core().get_atom(*atom_id).ok_or_else(|| RiddleError::NotFound(format!("Atom {}", *atom_id)))?.var_type(),
487            };
488            if !is_assignable_from(&expected_type, &arg_value_type) {
489                return Err(RiddleError::TypeError(format!("Argument '{}' expected to be of type '{}', got '{}'", arg_name, expected_type.full_name(), arg_value_type.full_name())));
490            }
491            function_env.set(arg_name.clone(), arg_value);
492        }
493        let scope: Rc<dyn Scope> = self.scope.clone();
494        for stmt in &self.statements {
495            execute(&scope, function_env.clone(), stmt)?;
496        }
497        if let Some(return_type) = &self.return_type {
498            function_env.get("__return").ok_or_else(|| RiddleError::RuntimeError("Function did not set return value".into())).and_then(|ret| {
499                let expected_type = get_type_by_path(self.scope.as_ref(), return_type)?;
500                let ret_type = match &ret {
501                    Slot::Primitive(p) => p.var_type(),
502                    Slot::ObjectRef(obj_id) => self.scope.core().get_object(*obj_id).ok_or_else(|| RiddleError::NotFound(format!("Object {}", *obj_id)))?.var_type(),
503                    Slot::AtomRef(atom_id) => self.scope.core().get_atom(*atom_id).ok_or_else(|| RiddleError::NotFound(format!("Atom {}", *atom_id)))?.var_type(),
504                };
505                if !is_assignable_from(&expected_type, &ret_type) { Err(RiddleError::TypeError(format!("Return value expected to be of type '{}', got '{}'", expected_type.full_name(), ret_type.full_name()))) } else { Ok(Some(ret)) }
506            })
507        } else {
508            Ok(None)
509        }
510    }
511}
512
513impl Scope for Function {
514    fn core(&self) -> Rc<dyn Core> {
515        self.scope.core()
516    }
517
518    fn scope(&self) -> Option<Rc<dyn Scope>> {
519        self.scope.scope()
520    }
521
522    fn get_fields(&self) -> Vec<Rc<Field>> {
523        self.scope.get_fields()
524    }
525
526    fn get_field(&self, name: &str) -> Option<Rc<Field>> {
527        self.scope.get_field(name)
528    }
529
530    fn get_function(&self, name: &str, types: &[Rc<dyn Type>]) -> Option<Rc<Function>> {
531        self.scope.get_function(name, types)
532    }
533
534    fn get_type(&self, name: &str) -> Option<Rc<dyn Type>> {
535        self.scope.get_type(name)
536    }
537
538    fn get_predicate(&self, name: &str) -> Option<Rc<Predicate>> {
539        self.scope.get_predicate(name)
540    }
541}
542
543/// Class-specific API surface layered on top of type and scope behavior.
544pub trait Class: Type + Scope {
545    fn parents(&self) -> &[Vec<String>];
546    fn constructors(&self) -> Vec<Rc<Constructor>>;
547    fn constructor(&self, args: &[Rc<dyn Type>]) -> Option<Rc<Constructor>>;
548    fn predicates(&self) -> Vec<Rc<Predicate>>;
549    fn classes(&self) -> Vec<Rc<dyn Class>>;
550    fn instances(&self) -> Vec<ObjectId>;
551    fn add_instance(&self, instance: ObjectId);
552}
553
554pub struct CommonClass {
555    scope: Rc<CommonScope>,
556    name: String,
557    parents: Vec<Vec<String>>,
558    constructors: RefCell<Vec<Rc<Constructor>>>,
559    instances: RefCell<Vec<ObjectId>>,
560}
561
562impl CommonClass {
563    /// Creates a class type from its parsed definition, including nested members.
564    pub fn new(parent_scope: Weak<dyn Scope>, mut class: ClassDef) -> Rc<Self> {
565        let name = std::mem::take(&mut class.name);
566        let parents = std::mem::take(&mut class.parents);
567        let constructors_def = if class.constructors.is_empty() { vec![ConstructorDef { args: Vec::new(), init: Vec::new(), statements: Vec::new() }] } else { std::mem::take(&mut class.constructors) };
568        let class = Rc::new(Self {
569            name,
570            parents,
571            constructors: RefCell::new(Vec::new()),
572            scope: CommonScope::from_class(parent_scope, class),
573            instances: RefCell::new(Vec::new()),
574        });
575        let weak_class = Rc::downgrade(&class);
576        class.constructors.borrow_mut().extend(constructors_def.into_iter().map(|c| Rc::new(Constructor::new(weak_class.clone(), c))));
577        class
578    }
579}
580
581impl Type for CommonClass {
582    fn name(&self) -> &str {
583        &self.name
584    }
585
586    fn full_name(&self) -> String {
587        if let Some(scope) = self.scope.scope.as_ref().and_then(|scope| scope.upgrade())
588            && let Some(class) = scope.as_class()
589        {
590            format!("{}.{}", class.full_name(), self.name)
591        } else {
592            self.name.clone()
593        }
594    }
595
596    fn as_class(self: Rc<Self>) -> Option<Rc<dyn Class>> {
597        Some(self)
598    }
599
600    fn new_instance(self: Rc<Self>) -> Slot {
601        let instance = self.core().new_object(self.clone());
602        self.instances.borrow_mut().push(instance);
603        for parent in &self.parents {
604            let parent_class = get_type_by_path(self.as_ref(), parent).expect("Parent class should exist").as_class().expect("Parent class should be a class");
605            parent_class.add_instance(instance);
606        }
607        Slot::ObjectRef(instance)
608    }
609}
610
611impl Scope for CommonClass {
612    fn core(&self) -> Rc<dyn Core> {
613        self.scope.core()
614    }
615
616    fn scope(&self) -> Option<Rc<dyn Scope>> {
617        self.scope.scope()
618    }
619
620    fn as_class(self: Rc<Self>) -> Option<Rc<dyn Class>> {
621        Some(self)
622    }
623
624    fn get_fields(&self) -> Vec<Rc<Field>> {
625        self.scope.get_fields()
626    }
627
628    fn get_field(&self, name: &str) -> Option<Rc<Field>> {
629        self.scope.get_field(name)
630    }
631
632    fn get_function(&self, name: &str, types: &[Rc<dyn Type>]) -> Option<Rc<Function>> {
633        self.scope.get_function(name, types)
634    }
635
636    fn get_type(&self, name: &str) -> Option<Rc<dyn Type>> {
637        self.scope.get_type(name)
638    }
639
640    fn get_predicate(&self, name: &str) -> Option<Rc<Predicate>> {
641        self.scope.get_predicate(name)
642    }
643}
644
645impl Class for CommonClass {
646    fn parents(&self) -> &[Vec<String>] {
647        &self.parents
648    }
649
650    fn constructors(&self) -> Vec<Rc<Constructor>> {
651        self.constructors.borrow().clone()
652    }
653
654    fn constructor(&self, args: &[Rc<dyn Type>]) -> Option<Rc<Constructor>> {
655        self.constructors
656            .borrow()
657            .iter()
658            .find(|c| {
659                if c.args().len() != args.len() {
660                    return false;
661                }
662                for ((arg_type, _), tp) in c.args().iter().zip(args.iter()) {
663                    if !tp.full_name().split('.').eq(arg_type.iter().map(|s| s.as_str())) {
664                        return false;
665                    }
666                }
667                true
668            })
669            .cloned()
670    }
671
672    fn predicates(&self) -> Vec<Rc<Predicate>> {
673        self.scope.predicates.borrow().values().cloned().collect()
674    }
675
676    fn classes(&self) -> Vec<Rc<dyn Class>> {
677        self.scope.types.borrow().values().filter_map(|t| t.clone().as_class()).collect()
678    }
679
680    fn instances(&self) -> Vec<ObjectId> {
681        self.instances.borrow().clone()
682    }
683
684    fn add_instance(&self, instance: ObjectId) {
685        self.instances.borrow_mut().push(instance);
686    }
687}
688
689/// Returns the resulting numeric type for arithmetic terms.
690///
691/// If all terms are int the result is int, otherwise mixed int/real terms yield
692/// real. Any other type combination results in a type error.
693pub fn arith_type(cr: &dyn Core, terms: &[Slot]) -> Result<Rc<dyn Type>, RiddleError> {
694    let types = terms
695        .iter()
696        .map(|t| match t {
697            Slot::Primitive(p) => Ok(p.var_type()),
698            Slot::ObjectRef(obj_id) => Err(RiddleError::TypeError(format!("Expected numeric type, got object reference to object {}", *obj_id))),
699            Slot::AtomRef(atom_id) => Err(RiddleError::TypeError(format!("Expected numeric type, got atom reference to atom {}", *atom_id))),
700        })
701        .collect::<Result<Vec<_>, _>>()?;
702    if types.iter().all(|t| t.name() == "int") {
703        Ok(cr.get_type("int").expect("int class not found"))
704    } else if types.iter().all(|t| t.name() == "int" || t.name() == "real") {
705        Ok(cr.get_type("real").expect("real class not found"))
706    } else {
707        Err(RiddleError::TypeError("Invalid types for arithmetic operation".into()))
708    }
709}
710
711/// Returns whether a value of source type can be assigned to target.
712///
713/// The check accepts exact type matches and direct parent/child relationships
714/// between class types.
715pub fn is_assignable_from(target: &Rc<dyn Type>, source: &Rc<dyn Type>) -> bool {
716    if Rc::ptr_eq(target, source) {
717        return true;
718    }
719
720    if let Some(target_class) = target.clone().as_class()
721        && let Some(source_class) = source.clone().as_class()
722        && is_subclass_of(source_class.clone(), &target_class.full_name())
723    {
724        return true;
725    }
726    false
727}
728
729fn is_subclass_of(current_class: Rc<dyn Class>, target_full_name: &str) -> bool {
730    for parent_path in current_class.parents() {
731        if parent_path.iter().map(|s| s.as_str()).eq(target_full_name.split('.')) {
732            return true;
733        }
734        if let Ok(parent_type) = get_type_by_path(&*current_class, parent_path)
735            && let Some(parent_class) = parent_type.as_class()
736            && is_subclass_of(parent_class, target_full_name)
737        {
738            return true;
739        }
740    }
741    false
742}
743
744pub struct Predicate {
745    scope: CommonScope,
746    name: String,
747    parents: Vec<Vec<String>>,
748    args: Vec<(Vec<String>, String)>,
749    statements: Vec<Statement>,
750    pub(crate) atoms: RefCell<Vec<AtomId>>,
751}
752
753impl Predicate {
754    /// Creates a predicate from its parsed definition.
755    pub fn new(scope: Weak<dyn Scope>, mut predicate: PredicateDef) -> Rc<Self> {
756        Rc::new(Self {
757            name: std::mem::take(&mut predicate.name),
758            parents: std::mem::take(&mut predicate.parents),
759            args: std::mem::take(&mut predicate.args),
760            statements: std::mem::take(&mut predicate.statements),
761            scope: CommonScope::from_predicate(scope, predicate),
762            atoms: RefCell::new(Vec::new()),
763        })
764    }
765
766    pub fn parents(&self) -> &[Vec<String>] {
767        &self.parents
768    }
769
770    pub fn args(&self) -> &[(Vec<String>, String)] {
771        &self.args
772    }
773
774    pub fn statements(&self) -> &[Statement] {
775        &self.statements
776    }
777
778    /// Executes predicate statements against a concrete atom.
779    pub fn call(self: Rc<Self>, atom: Rc<Atom>) -> Result<(), RiddleError> {
780        // we first execute parent predicates in declaration order, passing the same atom..
781        for parent in &self.parents {
782            let parent_predicate = get_predicate_by_path(&self.scope, parent)?;
783            parent_predicate.call(atom.clone())?;
784        }
785        let scope: Rc<dyn Scope> = self.clone();
786        for stmt in &self.statements {
787            execute(&scope, atom.clone(), stmt)?;
788        }
789        Ok(())
790    }
791
792    pub fn atoms(&self) -> Vec<AtomId> {
793        self.atoms.borrow().clone()
794    }
795}
796
797impl Type for Predicate {
798    fn name(&self) -> &str {
799        &self.name
800    }
801
802    fn new_instance(self: Rc<Self>) -> Slot {
803        panic!("Cannot create instance of a predicate")
804    }
805}
806
807impl Scope for Predicate {
808    fn core(&self) -> Rc<dyn Core> {
809        self.scope.core()
810    }
811
812    fn scope(&self) -> Option<Rc<dyn Scope>> {
813        self.scope.scope()
814    }
815
816    fn get_fields(&self) -> Vec<Rc<Field>> {
817        self.scope.get_fields()
818    }
819
820    fn get_field(&self, name: &str) -> Option<Rc<Field>> {
821        self.scope.get_field(name)
822    }
823
824    fn get_function(&self, name: &str, types: &[Rc<dyn Type>]) -> Option<Rc<Function>> {
825        self.scope.get_function(name, types)
826    }
827
828    fn get_type(&self, name: &str) -> Option<Rc<dyn Type>> {
829        self.scope.get_type(name)
830    }
831
832    fn get_predicate(&self, name: &str) -> Option<Rc<Predicate>> {
833        self.scope.get_predicate(name)
834    }
835}
836
837/// Resolves a type by a dotted path-like sequence of names.
838///
839/// The first segment is looked up in the provided [`Scope`], and each
840/// subsequent segment is resolved as a nested type of the previous class.
841///
842/// # Errors
843///
844/// Returns:
845/// - [`RiddleError::RuntimeError`] if `path` is empty.
846/// - [`RiddleError::NotFound`] if any path segment cannot be resolved.
847/// - [`RiddleError::NotAClass`] if an intermediate segment does not resolve to a class.
848pub fn get_type_by_path(scope: &dyn Scope, path: &[String]) -> Result<Rc<dyn Type>, RiddleError> {
849    let (first, rest) = path.split_first().ok_or_else(|| RiddleError::RuntimeError("Empty type path".into()))?;
850    rest.iter().try_fold(scope.get_type(first).ok_or_else(|| RiddleError::NotFound(first.clone()))?, |current, part| current.as_class().ok_or_else(|| RiddleError::NotAClass(first.clone()))?.get_type(part).ok_or_else(|| RiddleError::NotFound(format!("Class '{}' in path", part))))
851}
852
853/// Resolves a predicate by path.
854///
855/// All segments except the last are resolved as a type path via
856/// [`get_type_by_path`]. The last segment is then looked up as a predicate
857/// within the resolved class type.
858///
859/// # Errors
860///
861/// Returns:
862/// - [`RiddleError::RuntimeError`] if `path` is empty.
863/// - Any error returned by [`get_type_by_path`] for the prefix path.
864/// - [`RiddleError::NotAClass`] if the resolved type path is not a class.
865/// - [`RiddleError::NotFound`] if the final predicate cannot be resolved.
866pub fn get_predicate_by_path(scope: &dyn Scope, path: &[String]) -> Result<Rc<Predicate>, RiddleError> {
867    let (last, rest) = path.split_last().ok_or_else(|| RiddleError::RuntimeError("Empty predicate path".into()))?;
868    if rest.is_empty() {
869        scope.get_predicate(last).ok_or_else(|| RiddleError::NotFound(last.clone()))
870    } else {
871        get_type_by_path(scope, rest)?.as_class().ok_or_else(|| RiddleError::NotAClass(rest.join(".")))?.get_predicate(last).ok_or_else(|| RiddleError::NotFound(format!("Predicate '{}' in path", last)))
872    }
873}