rl_model/model/
expr.rs

1use super::*;
2use crate::parser::*;
3use std::collections::HashMap;
4
5#[derive(Debug, Clone)]
6pub enum Expr {
7    True,
8    False,
9    ResourceEq(Reference<ResourceId>, Reference<StateId>),
10    ResourceNe(Reference<ResourceId>, Reference<StateId>),
11    Not(Box<Expr>),
12    And(Box<Expr>, Box<Expr>),
13    Or(Box<Expr>, Box<Expr>),
14    Implies(Box<Expr>, Box<Expr>),
15}
16
17impl Expr {
18    pub fn resolve_resource(&mut self, map: &HashMap<String, ResourceId>) -> Result<(), RlError> {
19        match self {
20            Expr::True => Ok(()),
21            Expr::False => Ok(()),
22            Expr::ResourceEq(resource, _) => match resource {
23                Reference::Unresolved(name, pos) => match map.get(name) {
24                    Some(id) => {
25                        *resource = Reference::Resolved(*id);
26                        Ok(())
27                    }
28                    None => Err(RlError::Resolve {
29                        element: format!("resource '{}'", name),
30                        position: pos.clone(),
31                    }),
32                },
33                Reference::Resolved(_) => Ok(()),
34            },
35            Expr::ResourceNe(resource, _) => match resource {
36                Reference::Unresolved(name, pos) => match map.get(name) {
37                    Some(id) => {
38                        *resource = Reference::Resolved(*id);
39                        Ok(())
40                    }
41                    None => Err(RlError::Resolve {
42                        element: format!("resource '{}'", name),
43                        position: pos.clone(),
44                    }),
45                },
46                Reference::Resolved(_) => Ok(()),
47            },
48            Expr::Not(e) => e.resolve_resource(map),
49            Expr::And(l, r) => {
50                l.resolve_resource(map)?;
51                r.resolve_resource(map)
52            }
53            Expr::Or(l, r) => {
54                l.resolve_resource(map)?;
55                r.resolve_resource(map)
56            }
57            Expr::Implies(l, r) => {
58                l.resolve_resource(map)?;
59                r.resolve_resource(map)
60            }
61        }
62    }
63
64    pub fn resolve_state(&mut self, map: &HashMap<String, StateId>) -> Result<(), RlError> {
65        match self {
66            Expr::True => Ok(()),
67            Expr::False => Ok(()),
68            Expr::ResourceEq(_, state) => match state {
69                Reference::Unresolved(name, pos) => match map.get(name) {
70                    Some(id) => {
71                        *state = Reference::Resolved(*id);
72                        Ok(())
73                    }
74                    None => Err(RlError::Resolve {
75                        element: format!("state '{}'", name),
76                        position: pos.clone(),
77                    }),
78                },
79                Reference::Resolved(_) => Ok(()),
80            },
81            Expr::ResourceNe(_, state) => match state {
82                Reference::Unresolved(name, pos) => match map.get(name) {
83                    Some(id) => {
84                        *state = Reference::Resolved(*id);
85                        Ok(())
86                    }
87                    None => Err(RlError::Resolve {
88                        element: format!("state '{}'", name),
89                        position: pos.clone(),
90                    }),
91                },
92                Reference::Resolved(_) => Ok(()),
93            },
94            Expr::Not(e) => e.resolve_state(map),
95            Expr::And(l, r) => {
96                l.resolve_state(map)?;
97                r.resolve_state(map)
98            }
99            Expr::Or(l, r) => {
100                l.resolve_state(map)?;
101                r.resolve_state(map)
102            }
103            Expr::Implies(l, r) => {
104                l.resolve_state(map)?;
105                r.resolve_state(map)
106            }
107        }
108    }
109}
110
111impl ToLang for Expr {
112    fn to_lang(&self, skillset: &Skillset) -> String {
113        match self {
114            Expr::True => String::from("true"),
115            Expr::False => String::from("false"),
116            Expr::ResourceEq(resource, state) => {
117                format!(
118                    "{} == {}",
119                    resource.to_lang(skillset),
120                    state.to_lang(skillset)
121                )
122            }
123            Expr::ResourceNe(resource, state) => {
124                format!(
125                    "{} != {}",
126                    resource.to_lang(skillset),
127                    state.to_lang(skillset)
128                )
129            }
130            Expr::Not(e) => format!("(not {})", e.to_lang(skillset)),
131            Expr::And(l, r) => format!("({} and {})", l.to_lang(skillset), r.to_lang(skillset)),
132            Expr::Or(l, r) => format!("({} or {})", l.to_lang(skillset), r.to_lang(skillset)),
133            Expr::Implies(l, r) => format!("({} => {})", l.to_lang(skillset), r.to_lang(skillset)),
134        }
135    }
136}