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>)>); #[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}