conjure_core/rules/
subsitute_lettings.rs
1use std::rc::Rc;
2
3use conjure_macros::register_rule;
4
5use crate::{
6 ast::{Atom, Expression as Expr, SymbolTable},
7 rule_engine::{ApplicationError::RuleNotApplicable, ApplicationResult, Reduction},
8};
9
10#[register_rule(("Base", 5000))]
19fn substitute_value_lettings(expr: &Expr, symbols: &SymbolTable) -> ApplicationResult {
20 let Expr::Atomic(_, Atom::Reference(name)) = expr else {
21 return Err(RuleNotApplicable);
22 };
23
24 let decl = symbols.lookup(name).ok_or(RuleNotApplicable)?;
25 let value = decl.as_value_letting().ok_or(RuleNotApplicable)?;
26
27 Ok(Reduction::pure(value.clone()))
28}
29
30#[register_rule(("Base", 5000))]
32fn substitute_domain_lettings(expr: &Expr, symbols: &SymbolTable) -> ApplicationResult {
33 let Expr::Root(_, _) = expr else {
34 return Err(RuleNotApplicable);
35 };
36
37 let mut new_symbols = symbols.clone();
38 let mut has_changed = false;
39
40 for (_, mut decl) in symbols.clone().into_iter_local() {
41 let Some(mut var) = decl.as_var().cloned() else {
42 continue;
43 };
44
45 let old_domain = var.domain;
46 var.domain = old_domain.clone().resolve(symbols);
47 if old_domain != var.domain {
48 *(Rc::make_mut(&mut decl).as_var_mut().unwrap()) = var;
49 has_changed = true;
50 new_symbols.update_insert(decl);
51 };
52 }
53 if has_changed {
54 Ok(Reduction::with_symbols(expr.clone(), new_symbols))
55 } else {
56 Err(RuleNotApplicable)
57 }
58}