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