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