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