Skip to main content

riddle/
language.rs

1use crate::{
2    env::{BoolExpr, CommonEnv, Env, Var, to_cnf},
3    scope::{Scope, is_assignable_from},
4};
5use std::{
6    collections::{HashMap, VecDeque},
7    fmt,
8    rc::Rc,
9};
10
11#[derive(Debug)]
12pub enum RiddleError {
13    NotAnEnvironment(String),
14    NotAClass(String),
15    NotAPredicate(String),
16    TypeError(String),
17    NotFound(String),
18    InconsistencyError(String),
19    RuntimeError(String),
20}
21
22impl fmt::Display for RiddleError {
23    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24        match self {
25            RiddleError::NotAnEnvironment(name) => write!(f, "Variable '{}' is not an environment", name),
26            RiddleError::NotAClass(name) => write!(f, "Type '{}' is not a class", name),
27            RiddleError::NotAPredicate(name) => write!(f, "Predicate '{}' not found", name),
28            RiddleError::TypeError(msg) => write!(f, "Type error: {}", msg),
29            RiddleError::NotFound(name) => write!(f, "'{}' not found", name),
30            RiddleError::InconsistencyError(msg) => write!(f, "Inconsistency error: {}", msg),
31            RiddleError::RuntimeError(msg) => write!(f, "Runtime error: {}", msg),
32        }
33    }
34}
35
36#[derive(Debug, PartialEq)]
37pub struct ProblemDef {
38    pub methods: Vec<MethodDef>,
39    pub predicates: Vec<PredicateDef>,
40    pub classes: Vec<ClassDef>,
41    pub statements: Vec<Statement>,
42}
43
44pub type FieldDef = (Vec<String>, Vec<(String, Option<Expr>)>); // (type, [(name, optional initializer)])
45
46#[derive(Debug, PartialEq)]
47pub struct ClassDef {
48    pub name: String,
49    pub parents: Vec<Vec<String>>,
50    pub fields: Vec<FieldDef>,
51    pub constructors: Vec<ConstructorDef>,
52    pub methods: Vec<MethodDef>,
53    pub predicates: Vec<PredicateDef>,
54    pub classes: Vec<ClassDef>,
55}
56
57#[derive(Debug, PartialEq)]
58pub struct ConstructorDef {
59    pub args: Vec<(Vec<String>, String)>,
60    pub init: Vec<(String, Vec<Expr>)>,
61    pub statements: Vec<Statement>,
62}
63
64#[derive(Debug, PartialEq)]
65pub struct MethodDef {
66    pub return_type: Option<Vec<String>>,
67    pub name: String,
68    pub args: Vec<(Vec<String>, String)>,
69    pub statements: Vec<Statement>,
70}
71
72#[derive(Debug, PartialEq)]
73pub struct PredicateDef {
74    pub name: String,
75    pub args: Vec<(Vec<String>, String)>,
76    pub parents: Vec<Vec<String>>,
77    pub statements: Vec<Statement>,
78}
79
80#[derive(Debug, PartialEq, Clone)]
81pub enum Statement {
82    Expr(Expr),
83    LocalField { field_type: Vec<String>, fields: Vec<(String, Option<Expr>)> },
84    Assign { name: Vec<String>, value: Expr },
85    ForAll { var_type: Vec<String>, var_name: String, statements: Vec<Statement> },
86    Disjunction { disjuncts: Vec<(Vec<Statement>, Expr)> },
87    Formula { is_fact: bool, name: String, tau: Vec<String>, predicate_name: String, args: Vec<(String, Expr)> },
88    Return { value: Expr },
89}
90
91#[derive(Debug, PartialEq, Clone)]
92pub enum Expr {
93    Bool(bool),
94    Int(i64),
95    Real(i64, i64),
96    String(String),
97    QualifiedId { ids: Vec<String> },
98    Sum { terms: Vec<Expr> },
99    Opposite { term: Box<Expr> },
100    Not { term: Box<Expr> },
101    Mul { factors: Vec<Expr> },
102    Div { left: Box<Expr>, right: Box<Expr> },
103    Function { name: Vec<String>, args: Vec<Expr> },
104    Eq { left: Box<Expr>, right: Box<Expr> },
105    Neq { left: Box<Expr>, right: Box<Expr> },
106    Lt { left: Box<Expr>, right: Box<Expr> },
107    Leq { left: Box<Expr>, right: Box<Expr> },
108    Gt { left: Box<Expr>, right: Box<Expr> },
109    Geq { left: Box<Expr>, right: Box<Expr> },
110    Or { terms: Vec<Expr> },
111    And { terms: Vec<Expr> },
112    NewObject { class_name: Vec<String>, args: Vec<Expr> },
113}
114
115impl fmt::Display for ProblemDef {
116    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117        for method in &self.methods {
118            writeln!(f, "{}", method)?;
119        }
120        for predicate in &self.predicates {
121            writeln!(f, "{}", predicate)?;
122        }
123        for class in &self.classes {
124            writeln!(f, "{}", class)?;
125        }
126        for statement in &self.statements {
127            writeln!(f, "{}", statement)?;
128        }
129        Ok(())
130    }
131}
132
133impl fmt::Display for ClassDef {
134    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135        writeln!(f, "class {}{} {{", self.name, if !self.parents.is_empty() { format!(" extends {}", self.parents.iter().map(|p| p.join(".")).collect::<Vec<_>>().join(", ")) } else { String::new() })?;
136        for (field_type, fields) in &self.fields {
137            writeln!(f, "    {} {};", field_type.join("."), fields.iter().map(|(n, v)| format!("{}{}", n, v.as_ref().map(|v| format!(" = {}", v)).unwrap_or_default())).collect::<Vec<_>>().join(", "))?;
138        }
139        for constructor in &self.constructors {
140            writeln!(f, "    {}", constructor)?;
141        }
142        for method in &self.methods {
143            writeln!(f, "    {}", method)?;
144        }
145        for predicate in &self.predicates {
146            writeln!(f, "    {}", predicate)?;
147        }
148        write!(f, "}}")
149    }
150}
151
152impl fmt::Display for ConstructorDef {
153    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154        write!(f, "constructor({}) {{\n{}\n}}", self.args.iter().map(|(t, n)| format!("{} {}", t.join("."), n)).collect::<Vec<_>>().join(", "), self.statements.iter().map(|s| format!("    {}", s)).collect::<Vec<_>>().join("\n"))
155    }
156}
157
158impl fmt::Display for MethodDef {
159    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160        write!(
161            f,
162            "{} {}({}) {{\n{}\n}}",
163            self.return_type.as_ref().map(|t| t.join(".")).unwrap_or_else(|| "void".to_string()),
164            self.name,
165            self.args.iter().map(|(t, n)| format!("{} {}", t.join("."), n)).collect::<Vec<_>>().join(", "),
166            self.statements.iter().map(|s| format!("    {}", s)).collect::<Vec<_>>().join("\n")
167        )
168    }
169}
170
171impl fmt::Display for PredicateDef {
172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173        write!(f, "predicate {}({}) {{\n{}\n}}", self.name, self.args.iter().map(|(t, n)| format!("{} {}", t.join("."), n)).collect::<Vec<_>>().join(", "), self.statements.iter().map(|s| format!("    {}", s)).collect::<Vec<_>>().join("\n"))
174    }
175}
176
177impl fmt::Display for Statement {
178    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179        match self {
180            Statement::Expr(e) => write!(f, "{};", e),
181            Statement::LocalField { field_type, fields } => write!(f, "{} {};", field_type.join("."), fields.iter().map(|(n, v)| format!("{}{}", n, v.as_ref().map(|v| format!(" = {}", v)).unwrap_or_default())).collect::<Vec<_>>().join(", ")),
182            Statement::Assign { name, value } => write!(f, "{} = {};", name.join("."), value),
183            Statement::ForAll { var_type, var_name, statements } => write!(f, "for {} {} {{\n{}\n}}", var_type.join("."), var_name, statements.iter().map(|s| format!("    {}", s)).collect::<Vec<_>>().join("\n")),
184            Statement::Disjunction { disjuncts } => write!(f, "{{\n{}\n}}", disjuncts.iter().map(|(s, e)| format!("    {{\n{}\n    }}: {}", s.iter().map(|s| format!("        {}", s)).collect::<Vec<_>>().join("\n"), e)).collect::<Vec<_>>().join(" or ")),
185            Statement::Formula { is_fact, name, tau, predicate_name, args } => write!(f, "{} {} = new {}{}({});", if *is_fact { "fact" } else { "formula" }, name, if tau.is_empty() { String::new() } else { tau.join(".") + "." }, predicate_name, args.iter().map(|(n, e)| format!("{}: {}", n, e)).collect::<Vec<_>>().join(", ")),
186            Statement::Return { value } => write!(f, "return {};", value),
187        }
188    }
189}
190
191impl fmt::Display for Expr {
192    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193        match self {
194            Expr::Bool(b) => write!(f, "{}", b),
195            Expr::Int(i) => write!(f, "{}", i),
196            Expr::Real(n, d) => write!(f, "{}/{}", n, d),
197            Expr::String(s) => write!(f, "\"{}\"", s),
198            Expr::QualifiedId { ids } => write!(f, "{}", ids.join(".")),
199            Expr::Sum { terms } => write!(f, "({})", terms.iter().map(|t| format!("{}", t)).collect::<Vec<_>>().join(" + ")),
200            Expr::Opposite { term } => write!(f, "-({})", term),
201            Expr::Not { term } => write!(f, "!({})", term),
202            Expr::Mul { factors } => write!(f, "({})", factors.iter().map(|t| format!("{}", t)).collect::<Vec<_>>().join(" * ")),
203            Expr::Div { left, right } => write!(f, "({} / {})", left, right),
204            Expr::Function { name, args } => write!(f, "{}({})", name.join("."), args.iter().map(|a| format!("{}", a)).collect::<Vec<_>>().join(", ")),
205            Expr::Eq { left, right } => write!(f, "({} == {})", left, right),
206            Expr::Neq { left, right } => write!(f, "({} != {})", left, right),
207            Expr::Lt { left, right } => write!(f, "({} < {})", left, right),
208            Expr::Leq { left, right } => write!(f, "({} <= {})", left, right),
209            Expr::Gt { left, right } => write!(f, "({} > {})", left, right),
210            Expr::Geq { left, right } => write!(f, "({} >= {})", left, right),
211            Expr::Or { terms } => write!(f, "({})", terms.iter().map(|t| format!("{}", t)).collect::<Vec<_>>().join(" || ")),
212            Expr::And { terms } => write!(f, "({})", terms.iter().map(|t| format!("{}", t)).collect::<Vec<_>>().join(" && ")),
213            Expr::NewObject { class_name, args } => write!(f, "new {}({})", class_name.join("."), args.iter().map(|a| format!("{}", a)).collect::<Vec<_>>().join(", ")),
214        }
215    }
216}
217
218pub struct Disjunction {
219    pub scp: Rc<dyn Scope>,
220    pub env: Rc<dyn Env>,
221    pub disjuncts: Vec<(Vec<Statement>, Expr)>,
222}
223
224pub fn execute(scp: Rc<dyn Scope>, env: Rc<dyn Env>, stmt: &Statement) -> Result<(), RiddleError> {
225    match stmt {
226        Statement::Expr(expr) => {
227            if scp.clone().core().assert(to_cnf(evaluate(scp.clone(), env.clone(), expr)?)) {
228                Ok(())
229            } else {
230                Err(RiddleError::InconsistencyError(format!("Expression '{}' evaluated to false", expr)))
231            }
232        }
233        Statement::LocalField { field_type, fields } => {
234            let (first, rest) = field_type.split_first().ok_or_else(|| RiddleError::RuntimeError("Empty field type path".into()))?;
235            let fld_tp = scp.get_type(first).ok_or_else(|| RiddleError::NotFound(first.to_string()))?;
236            rest.iter().try_fold(fld_tp.clone(), |acc, id| acc.as_class().ok_or_else(|| RiddleError::NotAClass(first.to_string()))?.get_type(id).ok_or_else(|| RiddleError::NotFound(format!("Class '{}' in path", id))))?;
237            for (name, default) in fields {
238                if let Some(expr) = default {
239                    let value = evaluate(scp.clone(), env.clone(), expr)?;
240                    if !is_assignable_from(&fld_tp, &value.var_type()) {
241                        return Err(RiddleError::TypeError(format!("Default value for field '{}' is not assignable to field type '{}'", name, field_type.join("."))));
242                    }
243                    env.set(name.clone(), value);
244                } else if let Some(class) = fld_tp.clone().as_class() {
245                    let instances = class.instances().into_iter().map(|obj| obj as Rc<dyn Var>).collect::<Vec<_>>();
246                    if instances.is_empty() {
247                        return Err(RiddleError::RuntimeError(format!("No instances found for field '{}' of type '{}'", name, class.full_name())));
248                    } else if instances.len() == 1 {
249                        env.set(name.clone(), instances[0].clone());
250                    } else {
251                        env.set(name.clone(), scp.clone().core().new_var(class, instances.as_slice())?);
252                    }
253                } else {
254                    env.set(name.clone(), fld_tp.clone().new_instance());
255                }
256            }
257            Ok(())
258        }
259        Statement::Assign { name, value } => {
260            let value = evaluate(scp.clone(), env.clone(), value)?;
261            if name.len() == 1 {
262                env.set(name[0].clone(), value);
263                Ok(())
264            } else {
265                let (first, rest) = name.split_first().ok_or_else(|| RiddleError::RuntimeError("Empty assignment path".into()))?;
266                let root = env.get(first).ok_or_else(|| RiddleError::NotFound(first.to_string()))?;
267                let (last, rest) = rest.split_last().ok_or_else(|| RiddleError::RuntimeError("Empty assignment path".into()))?;
268                rest.iter().try_fold(root, |acc, id| acc.as_env().ok_or_else(|| RiddleError::NotAnEnvironment(id.to_string()))?.get(id).ok_or_else(|| RiddleError::NotFound(format!("Member '{}' in path", id))))?.as_env().ok_or_else(|| RiddleError::NotAnEnvironment(last.to_string()))?.set(last.to_string(), value);
269                Ok(())
270            }
271        }
272        Statement::ForAll { var_type, var_name, statements } => {
273            let (first, rest) = var_type.split_first().ok_or_else(|| RiddleError::RuntimeError("Empty variable type path".into()))?;
274            let class = scp.get_type(first).ok_or_else(|| RiddleError::NotFound(first.to_string()))?.as_class().ok_or_else(|| RiddleError::NotAClass(first.to_string()))?;
275            rest.iter().try_fold(class.clone(), |acc, id| acc.get_type(id).ok_or_else(|| RiddleError::NotFound(format!("Class '{}' in path", id)))?.as_class().ok_or_else(|| RiddleError::NotAClass(id.to_string())))?;
276            for instance in class.instances() {
277                let loop_env = Rc::new(CommonEnv::new(Some(env.clone())));
278                loop_env.set(var_name.clone(), instance);
279                for stmt in statements {
280                    execute(scp.clone(), loop_env.clone(), stmt)?;
281                }
282            }
283            Ok(())
284        }
285        Statement::Disjunction { disjuncts } => {
286            let disjunction = Disjunction { scp: scp.clone(), env: env.clone(), disjuncts: disjuncts.clone() };
287            scp.core().new_disjunction(disjunction);
288            Ok(())
289        }
290        Statement::Formula { is_fact, name, tau, predicate_name, args } => {
291            let tau = if tau.is_empty() {
292                None
293            } else {
294                let (first, rest) = tau.split_first().ok_or_else(|| RiddleError::RuntimeError("Empty identifier path".into()))?;
295                let root = env.get(first).ok_or_else(|| RiddleError::NotFound(first.to_string()))?;
296                let root = rest.iter().try_fold(root, |acc, id| acc.as_env().ok_or_else(|| RiddleError::NotAnEnvironment(id.to_string()))?.get(id).ok_or_else(|| RiddleError::NotFound(format!("Member '{}' in path", id))))?;
297                Some(root)
298            };
299            let predicate = if let Some(tau) = tau.clone() {
300                tau.as_ref().var_type().as_class().ok_or_else(|| RiddleError::NotAClass(format!("Type '{}' in tau path", tau.var_type().full_name())))?.get_predicate(predicate_name).ok_or_else(|| RiddleError::NotFound(format!("Predicate '{}' in class '{}'", predicate_name, tau.var_type().full_name())))?
301            } else {
302                scp.get_predicate(predicate_name).ok_or_else(|| RiddleError::NotFound(format!("Predicate '{}'", predicate_name)))?
303            };
304            let mut args: HashMap<String, Rc<dyn Var>> = args
305                .iter()
306                .map(|(n, e)| {
307                    let val = evaluate(scp.clone(), env.clone(), e)?;
308                    Ok((n.clone(), val))
309                })
310                .collect::<Result<_, _>>()?;
311            if let Some(tau) = tau {
312                args.insert("tau".to_string(), tau);
313            }
314            let mut pred_hierarchy = VecDeque::from(vec![predicate.clone()]);
315            while let Some(pred) = pred_hierarchy.pop_front() {
316                for (arg_type, name) in pred.args() {
317                    if !args.contains_key(name) {
318                        let (first, rest) = arg_type.split_first().ok_or_else(|| RiddleError::RuntimeError("Empty argument type path".into()))?;
319                        let arg_tp = scp.get_type(first).ok_or_else(|| RiddleError::NotFound(format!("Class '{}' in argument type path", first)))?;
320                        let arg_tp = rest.iter().try_fold(arg_tp, |acc, id| acc.as_class().ok_or_else(|| RiddleError::NotAClass(format!("Class '{}' in argument type path", first)))?.get_type(id).ok_or_else(|| RiddleError::NotFound(format!("Class '{}' in argument type path", id))))?;
321                        if let Some(class) = arg_tp.clone().as_class() {
322                            let instances = class.instances().into_iter().map(|obj| obj as Rc<dyn Var>).collect::<Vec<_>>();
323                            if instances.is_empty() {
324                                return Err(RiddleError::RuntimeError(format!("No instances found for argument '{}' of type '{}'", name, class.full_name())));
325                            } else if instances.len() == 1 {
326                                args.insert(name.clone(), instances[0].clone());
327                            } else {
328                                args.insert(name.clone(), scp.clone().core().new_var(class, instances.as_slice())?);
329                            }
330                        } else {
331                            args.insert(name.clone(), arg_tp.new_instance());
332                        }
333                    }
334                }
335                for parent_path in pred.parents() {
336                    let (predicate_name, class_path) = parent_path.split_last().ok_or_else(|| RiddleError::RuntimeError("Empty parent predicate path".into()))?;
337                    let parent_predicate = if class_path.is_empty() {
338                        scp.get_predicate(predicate_name).ok_or_else(|| RiddleError::NotFound(format!("Predicate '{}' in parent path", predicate_name)))?
339                    } else {
340                        let (first_class, nested_classes) = class_path.split_first().ok_or_else(|| RiddleError::RuntimeError("Empty parent predicate path".into()))?;
341                        let class_type = scp.get_type(first_class).ok_or_else(|| RiddleError::NotFound(format!("Class '{}' in parent path", first_class)))?;
342                        let class_type = nested_classes.iter().try_fold(class_type, |acc, class_name| {
343                            let acc_name = acc.full_name();
344                            acc.clone().as_class().ok_or_else(|| RiddleError::NotAClass(format!("Type '{}' in parent path is not a class", acc_name)))?.get_type(class_name).ok_or_else(|| RiddleError::NotFound(format!("Class '{}' in parent path", class_name)))
345                        })?;
346                        let class_type_name = class_type.full_name();
347                        class_type.clone().as_class().ok_or_else(|| RiddleError::NotAClass(format!("Type '{}' in parent path is not a class", class_type_name)))?.get_predicate(predicate_name).ok_or_else(|| RiddleError::NotFound(format!("Predicate '{}' in parent path", predicate_name)))?
348                    };
349                    pred_hierarchy.push_back(parent_predicate);
350                }
351            }
352            let atom = predicate.new_atom(*is_fact, args);
353            env.set(name.clone(), atom);
354            Ok(())
355        }
356        Statement::Return { value } => {
357            let ret = evaluate(scp.clone(), env.clone(), value)?;
358            env.set("__return".to_string(), ret);
359            Ok(())
360        }
361    }
362}
363
364pub fn evaluate(scp: Rc<dyn Scope>, env: Rc<dyn Env>, expr: &Expr) -> Result<Rc<dyn Var>, RiddleError> {
365    match expr {
366        Expr::Bool(bool) => {
367            let evaluated_term = scp.clone().core().new_bool(*bool);
368            Ok(Rc::new(BoolExpr::Term { var_type: Rc::downgrade(&scp.core().bool_type()), term: evaluated_term }))
369        }
370        Expr::Int(int) => Ok(scp.core().new_int(*int)),
371        Expr::Real(num, den) => Ok(scp.core().new_real(*num, *den)),
372        Expr::String(string) => Ok(scp.core().new_string(string)),
373        Expr::QualifiedId { ids } => {
374            let (first, rest) = ids.split_first().ok_or_else(|| RiddleError::RuntimeError("Empty identifier path".into()))?;
375            let root = env.get(first).ok_or_else(|| RiddleError::NotFound(first.to_string()))?;
376            rest.iter().try_fold(root, |acc, id| acc.as_env().ok_or_else(|| RiddleError::NotAnEnvironment(id.to_string()))?.get(id).ok_or_else(|| RiddleError::NotFound(format!("Member '{}' in path", id))))
377        }
378        Expr::Sum { terms } => {
379            let evaluated_terms: Vec<Rc<dyn Var>> = terms.iter().map(|t| evaluate(scp.clone(), env.clone(), t)).collect::<Result<_, _>>()?;
380            Ok(scp.core().sum(&evaluated_terms)?)
381        }
382        Expr::Opposite { term } => {
383            let evaluated_term = evaluate(scp.clone(), env, term)?;
384            Ok(scp.core().opposite(evaluated_term)?)
385        }
386        Expr::Not { term } => {
387            let evaluated_term = evaluate(scp.clone(), env, term)?.as_any().downcast::<BoolExpr>().map_err(|_| RiddleError::TypeError("Expected a boolean expression in 'not' operator".into()))?;
388            Ok(Rc::new(BoolExpr::Not { var_type: Rc::downgrade(&scp.core().bool_type()), term: evaluated_term }))
389        }
390        Expr::Mul { factors } => {
391            let evaluated_factors: Vec<Rc<dyn Var>> = factors.iter().map(|f| evaluate(scp.clone(), env.clone(), f)).collect::<Result<_, _>>()?;
392            Ok(scp.core().mul(&evaluated_factors)?)
393        }
394        Expr::Div { left, right } => {
395            let evaluated_left = evaluate(scp.clone(), env.clone(), left)?;
396            let evaluated_right = evaluate(scp.clone(), env, right)?;
397            Ok(scp.core().div(evaluated_left, evaluated_right)?)
398        }
399        Expr::Function { name, args } => {
400            let evaluated_args: Vec<Rc<dyn Var>> = args.iter().map(|a| evaluate(scp.clone(), env.clone(), a)).collect::<Result<_, _>>()?;
401            let method = scp.get_method(name.last().unwrap(), &evaluated_args.iter().map(|arg| arg.var_type()).collect::<Vec<_>>()).ok_or_else(|| RiddleError::NotFound(format!("Method '{}' with specified argument types", name.join("."))))?;
402            method.call(env, evaluated_args)?.ok_or_else(|| RiddleError::RuntimeError(format!("Method '{}' did not return a value", name.join("."))))
403        }
404        Expr::Eq { left, right } => {
405            let evaluated_left = evaluate(scp.clone(), env.clone(), left)?;
406            let evaluated_right = evaluate(scp.clone(), env, right)?;
407            Ok(Rc::new(BoolExpr::Eq {
408                var_type: Rc::downgrade(&scp.core().bool_type()),
409                left: evaluated_left,
410                right: evaluated_right,
411            }))
412        }
413        Expr::Neq { left, right } => {
414            let evaluated_left = evaluate(scp.clone(), env.clone(), left)?;
415            let evaluated_right = evaluate(scp.clone(), env, right)?;
416            Ok(Rc::new(BoolExpr::Not {
417                var_type: Rc::downgrade(&scp.clone().core().bool_type()),
418                term: Rc::new(BoolExpr::Eq {
419                    var_type: Rc::downgrade(&scp.core().bool_type()),
420                    left: evaluated_left,
421                    right: evaluated_right,
422                }),
423            }))
424        }
425        Expr::Lt { left, right } => {
426            let evaluated_left = evaluate(scp.clone(), env.clone(), left)?;
427            let evaluated_right = evaluate(scp.clone(), env, right)?;
428            Ok(Rc::new(BoolExpr::Lt {
429                var_type: Rc::downgrade(&scp.core().bool_type()),
430                left: evaluated_left,
431                right: evaluated_right,
432            }))
433        }
434        Expr::Leq { left, right } => {
435            let evaluated_left = evaluate(scp.clone(), env.clone(), left)?;
436            let evaluated_right = evaluate(scp.clone(), env, right)?;
437            Ok(Rc::new(BoolExpr::Leq {
438                var_type: Rc::downgrade(&scp.core().bool_type()),
439                left: evaluated_left,
440                right: evaluated_right,
441            }))
442        }
443        Expr::Geq { left, right } => {
444            let evaluated_left = evaluate(scp.clone(), env.clone(), left)?;
445            let evaluated_right = evaluate(scp.clone(), env, right)?;
446            Ok(Rc::new(BoolExpr::Leq {
447                var_type: Rc::downgrade(&scp.core().bool_type()),
448                left: evaluated_right,
449                right: evaluated_left,
450            }))
451        }
452        Expr::Gt { left, right } => {
453            let evaluated_left = evaluate(scp.clone(), env.clone(), left)?;
454            let evaluated_right = evaluate(scp.clone(), env, right)?;
455            Ok(Rc::new(BoolExpr::Lt {
456                var_type: Rc::downgrade(&scp.core().bool_type()),
457                left: evaluated_right,
458                right: evaluated_left,
459            }))
460        }
461        Expr::Or { terms } => {
462            let evaluated_terms: Vec<Rc<BoolExpr>> = terms.iter().map(|t| evaluate(scp.clone(), env.clone(), t).expect("Expected a boolean expression in 'or' operator").as_any().downcast::<BoolExpr>().expect("Expected a boolean expression in 'or' operator")).collect();
463            Ok(Rc::new(BoolExpr::Or { var_type: Rc::downgrade(&scp.core().bool_type()), terms: evaluated_terms }))
464        }
465        Expr::And { terms } => {
466            let evaluated_terms: Vec<Rc<BoolExpr>> = terms.iter().map(|t| evaluate(scp.clone(), env.clone(), t).expect("Expected a boolean expression in 'and' operator").as_any().downcast::<BoolExpr>().expect("Expected a boolean expression in 'and' operator")).collect();
467            Ok(Rc::new(BoolExpr::And { var_type: Rc::downgrade(&scp.core().bool_type()), terms: evaluated_terms }))
468        }
469        Expr::NewObject { class_name, args } => {
470            let (first, rest) = class_name.split_first().ok_or_else(|| RiddleError::RuntimeError("Empty class name".into()))?;
471            let class = scp.get_type(first).ok_or_else(|| RiddleError::NotFound(first.to_string()))?.as_class().ok_or_else(|| RiddleError::NotAClass(first.to_string()))?;
472            rest.iter().try_fold(class.clone(), |acc, id| acc.get_type(id).ok_or_else(|| RiddleError::NotFound(format!("Class '{}' in path", id)))?.as_class().ok_or_else(|| RiddleError::NotAClass(id.to_string())))?;
473            let evaluated_args: Vec<Rc<dyn Var>> = args.iter().map(|a| evaluate(scp.clone(), env.clone(), a)).collect::<Result<_, _>>()?;
474            let constructor = class.constructor(&evaluated_args.iter().map(|arg| arg.var_type()).collect::<Vec<_>>()).ok_or_else(|| RiddleError::NotFound(format!("Constructor for class '{}' with specified argument types", class_name.join("."))))?;
475            constructor.call(env, evaluated_args)?.ok_or_else(|| RiddleError::RuntimeError(format!("Constructor for class '{}' did not return a value", class_name.join("."))))
476        }
477    }
478}